Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Bitwise enhance that is new method imported from vital-codec library's Vim.Type.Number module #675

Merged
merged 4 commits into from
Sep 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 101 additions & 122 deletions autoload/vital/__vital__/Bitwise.vim
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
let s:save_cpo = &cpo
set cpo&vim

" inner utility

let s:bits = has('num64') ? 64 : 32
let s:mask = s:bits - 1
let s:mask32 = 32 - 1
Expand All @@ -16,6 +18,11 @@ unlet s:i

let s:min = s:pow2[-1]

" 32bit/64bit common method
function! s:_throw(msg) abort
throw 'vital: Bitwise: ' . a:msg
endfunction

" compare as unsigned int
function! s:compare(a, b) abort
if (a:a >= 0 && a:b >= 0) || (a:a < 0 && a:b < 0)
Expand All @@ -26,16 +33,19 @@ function! s:compare(a, b) abort
endfunction

function! s:lshift(a, n) abort
return a:a * s:pow2[s:and(a:n, s:mask)]
return a:a * s:pow2[and(a:n, s:mask)]
endfunction

function! s:rshift(a, n) abort
let n = s:and(a:n, s:mask)
let n = and(a:n, s:mask)
return n == 0 ? a:a :
\ a:a < 0 ? (a:a - s:min) / s:pow2[n] + s:pow2[-2] / s:pow2[n - 1]
\ : a:a / s:pow2[n]
endfunction

" 32bit or 64bit specific method
" define sign_extension
" lshift32/rshift32 64bit only implementation.
if has('num64')
" NOTE:
" An int literal larger than or equal to 0x8000000000000000 will be rounded
Expand All @@ -62,137 +72,106 @@ else
endfunction
endif


let s:builtin_functions_exist = exists('*and')
" 32bit or 64bit specific method
" builtin and funcref setup at module creation time.
" define and/or/xor/invert built-in
" lshift32/rshift32 32bit only altnative define.
function! s:_vital_created(module) abort
if s:builtin_functions_exist
for op in ['and', 'or', 'xor', 'invert']
let a:module[op] = function(op)
let s:[op] = a:module[op]
endfor
endif
for op in ['and', 'or', 'xor', 'invert']
let a:module[op] = function(op)
let s:[op] = a:module[op]
endfor
if !has('num64')
let a:module.lshift32 = a:module.lshift
let a:module.rshift32 = a:module.rshift
endif
endfunction

if s:builtin_functions_exist
finish
endif
" setup at module loaded time.
" define inner utility part2 : use defined method
function! s:_vital_loaded(V) abort
if has('num64')
let s:mask32bit = 0xFFFFFFFF
let s:mask64bit = or(
\ s:lshift(s:mask32bit, 32),
\ s:mask32bit
\)
else
let s:mask32bit = or(
\ s:lshift(0xFFFF, 16),
\ 0xFFFF
\)
endif
endfunction

" 32bit/64bit common method part2 : use defined method

function! s:invert(a) abort
return -a:a - 1
function! s:uint8(value) abort
return and(a:value, 0xFF)
endfunction

function! s:and(a, b) abort
let a = a:a < 0 ? a:a - s:min : a:a
let b = a:b < 0 ? a:b - s:min : a:b
let r = 0
let n = 1
while a && b
let r += s:and[a % 0x10][b % 0x10] * n
let a = a / 0x10
let b = b / 0x10
let n = n * 0x10
endwhile
if (a:a < 0) && (a:b < 0)
let r += s:min
endif
return r
endfunction

function! s:or(a, b) abort
let a = a:a < 0 ? a:a - s:min : a:a
let b = a:b < 0 ? a:b - s:min : a:b
let r = 0
let n = 1
while a || b
let r += s:or[a % 0x10][b % 0x10] * n
let a = a / 0x10
let b = b / 0x10
let n = n * 0x10
endwhile
if (a:a < 0) || (a:b < 0)
let r += s:min
endif
return r
endfunction

function! s:xor(a, b) abort
let a = a:a < 0 ? a:a - s:min : a:a
let b = a:b < 0 ? a:b - s:min : a:b
let r = 0
let n = 1
while a || b
let r += s:xor[a % 0x10][b % 0x10] * n
let a = a / 0x10
let b = b / 0x10
let n = n * 0x10
endwhile
if (a:a < 0) != (a:b < 0)
let r += s:min
endif
return r
endfunction

let s:and = [
\ [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
\ [0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1],
\ [0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2],
\ [0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3],
\ [0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4],
\ [0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5, 0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5],
\ [0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6, 0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6],
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7],
\ [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8],
\ [0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x8, 0x9, 0x8, 0x9, 0x8, 0x9, 0x8, 0x9],
\ [0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x8, 0x8, 0xA, 0xA, 0x8, 0x8, 0xA, 0xA],
\ [0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x8, 0x9, 0xA, 0xB, 0x8, 0x9, 0xA, 0xB],
\ [0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x8, 0x8, 0x8, 0x8, 0xC, 0xC, 0xC, 0xC],
\ [0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5, 0x8, 0x9, 0x8, 0x9, 0xC, 0xD, 0xC, 0xD],
\ [0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6, 0x8, 0x8, 0xA, 0xA, 0xC, 0xC, 0xE, 0xE],
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF]
\ ]

let s:or = [
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
\ [0x1, 0x1, 0x3, 0x3, 0x5, 0x5, 0x7, 0x7, 0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF],
\ [0x2, 0x3, 0x2, 0x3, 0x6, 0x7, 0x6, 0x7, 0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF],
\ [0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF],
\ [0x4, 0x5, 0x6, 0x7, 0x4, 0x5, 0x6, 0x7, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF],
\ [0x5, 0x5, 0x7, 0x7, 0x5, 0x5, 0x7, 0x7, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF],
\ [0x6, 0x7, 0x6, 0x7, 0x6, 0x7, 0x6, 0x7, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF],
\ [0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF],
\ [0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
\ [0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF, 0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF],
\ [0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF, 0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF],
\ [0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF, 0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF],
\ [0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF],
\ [0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF],
\ [0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF],
\ [0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF]
\ ]

let s:xor = [
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
\ [0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE],
\ [0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD],
\ [0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC],
\ [0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB],
\ [0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA],
\ [0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9],
\ [0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8],
\ [0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7],
\ [0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6],
\ [0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5],
\ [0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4],
\ [0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3],
\ [0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2],
\ [0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1],
\ [0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0]
\ ]
function! s:uint16(value) abort
return and(a:value, 0xFFFF)
endfunction

function! s:uint32(value) abort
return and(a:value, s:mask32bit)
endfunction

function! s:rotate8l(data, bits) abort
let data = s:uint8(a:data)
return s:uint8(or(s:lshift(data, a:bits),
\ s:rshift(data, 8 - a:bits)))
endfunction
function! s:rotate8r(data, bits) abort
return s:rotate8l(a:data, 8 - a:bits)
endfunction

function! s:rotate16l(data, bits) abort
let data = s:uint16(a:data)
return s:uint16(or(s:lshift(data, a:bits),
\ s:rshift(data, 16 - a:bits)))
endfunction
function! s:rotate16r(data, bits) abort
return s:rotate16l(a:data, 16 - a:bits)
endfunction

function! s:rotate32l(data, bits) abort
let data = s:uint32(a:data)
return s:uint32(or(s:lshift(data, a:bits),
\ s:rshift(data, 32 - a:bits)))
endfunction
function! s:rotate32r(data, bits) abort
return s:rotate32l(a:data, 32 - a:bits)
endfunction

" 32bit or 64bit specific method part2 : use defined method
" define uint64/rotate64l 64bit only implementation.
" 32bit throw exception.
if has('num64')
function! s:uint64(value) abort
return and(a:value, s:mask64bit)
endfunction

function! s:rotate64l(data, bits) abort
let data = s:uint64(a:data)
return s:uint64(or(s:lshift(data, a:bits),
\ s:rshift(data, 64 - a:bits)))
endfunction
else
function! s:uint64(value) abort
call s:_throw('64bit unsupport.')
endfunction

function! s:rotate64l(data, bits) abort
call s:_throw('64bit unsupport.')
endfunction
endif

" When 32bit throw exception.
function! s:rotate64r(data, bits) abort
return s:rotate64l(a:data, 64 - a:bits)
endfunction

let &cpo = s:save_cpo
unlet s:save_cpo
Expand Down
44 changes: 44 additions & 0 deletions doc/vital/Bitwise.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,49 @@ rshift32({expr}, {bits}) *Vital.Bitwise.rshift32()*
With |+num64|, upper 32bits of {expr} is ignored.


uint8({int}) *Vital.Bitwise.uint8()*
Return uint8 (1 byte) casted integer from {int}.

uint16({int}) *Vital.Bitwise.uint16()*
Return uint16 (2 byte) casted integer from {int}.

uint32({int}) *Vital.Bitwise.uint32()*
Return uint32 (4 byte) casted integer from {int}.

uint64({int}) *Vital.Bitwise.uint64()*
Return uint64 (8 byte) casted integer from {int}.
NOTE:Support only |+num64|.

rotate8l({int}, {bits}) *Vital.Bitwise.rotate8l()*
Return value that is {bits}-bit left bit-rotated with {int} as uint8.
Ex. >
echo printf('08b' B.rotate8(0b11001001, 3)
" 01001110
" 110 <-- 01001 <-- 110
<

rotate8r({int}, {bits}) *Vital.Bitwise.rotate8r()*
Same as |Vital.Bitwise.rotate8l()|, shift right.

rotate16l({int}, {bits}) *Vital.Bitwise.rotate16l()*
Return value that is {bits}-bit left bit-rotated with {int} as uint16.

rotate16r({int}, {bits}) *Vital.Bitwise.rotate16r()*
Same as |Vital.Bitwise.rotate16l()|, shift right.

rotate32l({int}, {bits}) *Vital.Bitwise.rotate32l()*
Return value that is {bits}-bit left bit-rotated with {int} as uint32.

rotate32r({int}, {bits}) *Vital.Bitwise.rotate32r()*
Same as |Vital.Bitwise.rotate32l()|, shift right.

rotate64l({int}, {bits}) *Vital.Bitwise.rotate64l()*
Return value that is {bits}-bit left bit-rotated with {int} as uint64.
NOTE:Support only |+num64|.

rotate64r({int}, {bits}) *Vital.Bitwise.rotate64r()*
Same as |Vital.Bitwise.rotate64l()|, shift right.
NOTE:Support only |+num64|.

==============================================================================
vim:tw=78:fo=tcq2mM:ts=8:ft=help:norl
Loading