mirror of
https://github.com/inkarkat/vim-ingo-library.git
synced 2026-10-01 12:56:44 +02:00
101 lines
3.3 KiB
VimL
101 lines
3.3 KiB
VimL
" ingo/nary.vim: Functions for working with tuples of numbers in a fixed range.
|
|
"
|
|
" DEPENDENCIES:
|
|
"
|
|
" Copyright: (C) 2017 Ingo Karkat
|
|
" The VIM LICENSE applies to this script; see ':help copyright'.
|
|
"
|
|
" Maintainer: Ingo Karkat <ingo@karkat.de>
|
|
"
|
|
" REVISION DATE REMARKS
|
|
" 1.030.001 14-May-2017 file creation
|
|
|
|
function! ingo#nary#FromNumber( n, number, ... )
|
|
"******************************************************************************
|
|
"* PURPOSE:
|
|
" Turn the integer a:number into a (little-endian) List of values from [0..n).
|
|
"* ASSUMPTIONS / PRECONDITIONS:
|
|
" None.
|
|
"* EFFECTS / POSTCONDITIONS:
|
|
" None.
|
|
"* INPUTS:
|
|
" a:n Maximum number that can be represented by one List element.
|
|
" a:number Positive integer.
|
|
" a:elementNum Optional number of elements to use. If specified and
|
|
" a:number cannot be represented by it, a exception is thrown.
|
|
" If a:elementNum is negative, only the lower elements will be
|
|
" returned. If omitted, the minimal amount of elements is
|
|
" used.
|
|
"* RETURN VALUES:
|
|
" List of [e0, e1, e2, ...] values; lowest come first.
|
|
"******************************************************************************
|
|
let l:number = a:number
|
|
let l:result = []
|
|
let l:elementCnt = 0
|
|
let l:elementMax = (a:0 ? ingo#compat#abs(a:1) : 0)
|
|
|
|
while 1
|
|
" Encode this little-endian.
|
|
call add(l:result, l:number % a:n)
|
|
let l:number = l:number / a:n
|
|
let l:elementCnt += 1
|
|
|
|
if l:elementMax && l:elementCnt == l:elementMax
|
|
if a:1 > 0 && l:number != 0
|
|
throw printf('FromNumber: Cannot represent %d in %d elements', a:number, l:elementMax)
|
|
endif
|
|
break
|
|
elseif ! a:0 && l:number == 0
|
|
break
|
|
endif
|
|
endwhile
|
|
return l:result
|
|
endfunction
|
|
function! ingo#nary#ToNumber( n, elements )
|
|
"******************************************************************************
|
|
"* PURPOSE:
|
|
" Turn the (little-endian) List of boolean values from [0..n) into a number.
|
|
"* ASSUMPTIONS / PRECONDITIONS:
|
|
" None.
|
|
"* EFFECTS / POSTCONDITIONS:
|
|
" None.
|
|
"* INPUTS:
|
|
" a:n Maximum number that can be represented by one List element.
|
|
" a:elements List of [e0, e1, e2, ...] values; lowest elements come first.
|
|
"* RETURN VALUES:
|
|
" Positive integer represented by a:elements.
|
|
"******************************************************************************
|
|
let l:number = 0
|
|
let l:factor = 1
|
|
while ! empty(a:elements)
|
|
let l:number += l:factor * remove(a:elements, 0)
|
|
let l:factor = l:factor * a:n
|
|
endwhile
|
|
return l:number
|
|
endfunction
|
|
|
|
function! ingo#nary#ElementsRequired( n, number )
|
|
"******************************************************************************
|
|
"* PURPOSE:
|
|
" Determine the number of elements within [0..n) required to represent a:number.
|
|
"* ASSUMPTIONS / PRECONDITIONS:
|
|
" None.
|
|
"* EFFECTS / POSTCONDITIONS:
|
|
" None.
|
|
"* INPUTS:
|
|
" a:n Maximum number that can be represented by one List element.
|
|
" a:number Positive integer.
|
|
"* RETURN VALUES:
|
|
" Number of elements required to represent numbers between 0 and a:number.
|
|
"******************************************************************************
|
|
let l:elementCnt = 1
|
|
let l:max = a:n
|
|
while a:number >= l:max
|
|
let l:elementCnt += 1
|
|
let l:max = l:max * a:n
|
|
endwhile
|
|
return l:elementCnt
|
|
endfunction
|
|
|
|
" vim: set ts=8 sts=4 sw=4 noexpandtab ff=unix fdm=syntax :
|