summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Gesang <megas.kapaneus@gmail.com>2013-04-07 18:23:34 +0200
committerPhilipp Gesang <megas.kapaneus@gmail.com>2013-04-07 18:23:34 +0200
commitb7f568675411e081301e589c6efb863a2d844817 (patch)
treeda2b9e6edd64656be35d7022074fbb8b7332c6f5
parent44173ba49717a356edf1c09f892f6909cad43481 (diff)
downloadlualibs-b7f568675411e081301e589c6efb863a2d844817.tar.gz
update l-number
-rw-r--r--lualibs-number.lua241
1 files changed, 157 insertions, 84 deletions
diff --git a/lualibs-number.lua b/lualibs-number.lua
index a4dbe3b..001ca31 100644
--- a/lualibs-number.lua
+++ b/lualibs-number.lua
@@ -6,7 +6,8 @@ if not modules then modules = { } end modules ['l-number'] = {
license = "see context related readme files"
}
--- this module will be replaced when we have the bit library
+-- this module will be replaced when we have the bit library .. the number based sets
+-- might go away
local tostring, tonumber = tostring, tonumber
local format, floor, match, rep = string.format, math.floor, string.match, string.rep
@@ -16,10 +17,129 @@ local lpegmatch = lpeg.match
number = number or { }
local number = number
--- a,b,c,d,e,f = number.toset(100101)
+if bit32 then -- I wonder if this is faster
+
+ local btest, bor = bit32.btest, bit32.bor
+
+ function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+ end
+
+ number.hasbit = btest
+ number.setbit = bor
+
+ function number.setbit(x,p) -- why not bor?
+ return btest(x,p) and x or x + p
+ end
+
+ function number.clearbit(x,p)
+ return btest(x,p) and x - p or x
+ end
+
+else
+
+ -- http://ricilake.blogspot.com/2007/10/iterating-bits-in-lua.html
+
+ function number.bit(p)
+ return 2 ^ (p - 1) -- 1-based indexing
+ end
+
+ function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
+ return x % (p + p) >= p
+ end
+
+ function number.setbit(x, p)
+ return (x % (p + p) >= p) and x or x + p
+ end
+
+ function number.clearbit(x, p)
+ return (x % (p + p) >= p) and x - p or x
+ end
-function number.toset(n)
- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
+end
+
+-- print(number.tobitstring(8))
+-- print(number.tobitstring(14))
+-- print(number.tobitstring(66))
+-- print(number.tobitstring(0x00))
+-- print(number.tobitstring(0xFF))
+-- print(number.tobitstring(46260767936,4))
+
+if bit32 then
+
+ local bextract = bit32.extract
+
+ local t = {
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ "0", "0", "0", "0", "0", "0", "0", "0",
+ }
+
+ function number.tobitstring(b,m)
+ -- if really needed we can speed this one up
+ -- because small numbers need less extraction
+ local n = 32
+ for i=0,31 do
+ local v = bextract(b,i)
+ local k = 32 - i
+ if v == 1 then
+ n = k
+ t[k] = "1"
+ else
+ t[k] = "0"
+ end
+ end
+ if m then
+ m = 33 - m * 8
+ if m < 1 then
+ m = 1
+ end
+ return concat(t,"",m)
+ elseif n < 8 then
+ return concat(t)
+ elseif n < 16 then
+ return concat(t,"",9)
+ elseif n < 24 then
+ return concat(t,"",17)
+ else
+ return concat(t,"",25)
+ end
+ end
+
+else
+
+ function number.tobitstring(n,m)
+ if n > 0 then
+ local t = { }
+ while n > 0 do
+ insert(t,1,n % 2 > 0 and 1 or 0)
+ n = floor(n/2)
+ end
+ local nn = 8 - #t % 8
+ if nn > 0 and nn < 8 then
+ for i=1,nn do
+ insert(t,1,0)
+ end
+ end
+ if m then
+ m = m * 8 - #t
+ if m > 0 then
+ insert(t,1,rep("0",m))
+ end
+ end
+ return concat(t)
+ elseif m then
+ rep("00000000",m)
+ else
+ return "00000000"
+ end
+ end
+
+end
+
+function number.valid(str,default)
+ return tonumber(str) or default or nil
end
function number.toevenhex(n)
@@ -31,104 +151,57 @@ function number.toevenhex(n)
end
end
--- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
--- on
+-- a,b,c,d,e,f = number.toset(100101)
+--
+-- function number.toset(n)
+-- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
+-- end
+--
+-- -- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
+-- -- on
--
-- for i=1,1000000 do
-- local a,b,c,d,e,f,g,h = number.toset(12345678)
-- local a,b,c,d = number.toset(1234)
-- local a,b,c = number.toset(123)
+-- local a,b,c = number.toset("123")
-- end
---
--- of course dedicated "(.)(.)(.)(.)" matches are even faster
-local one = lpeg.C(1-lpeg.S(''))^1
+local one = lpeg.C(1-lpeg.S('')/tonumber)^1
function number.toset(n)
return lpegmatch(one,tostring(n))
end
-function number.bits(n,zero)
- local t, i = { }, (zero and 0) or 1
- while n > 0 do
+-- function number.bits(n,zero)
+-- local t, i = { }, (zero and 0) or 1
+-- while n > 0 do
+-- local m = n % 2
+-- if m > 0 then
+-- insert(t,1,i)
+-- end
+-- n = floor(n/2)
+-- i = i + 1
+-- end
+-- return t
+-- end
+--
+-- -- a bit faster
+
+local function bits(n,i,...)
+ if n > 0 then
local m = n % 2
+ local n = floor(n/2)
if m > 0 then
- insert(t,1,i)
- end
- n = floor(n/2)
- i = i + 1
- end
- return t
-end
-
---~ http://ricilake.blogspot.com/2007/10/iterating-bits-in-lua.html
-
-function number.bit(p)
- return 2 ^ (p - 1) -- 1-based indexing
-end
-
-function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
- return x % (p + p) >= p
-end
-
-function number.setbit(x, p)
- return (x % (p + p) >= p) and x or x + p
-end
-
-function number.clearbit(x, p)
- return (x % (p + p) >= p) and x - p or x
-end
-
---~ function number.tobitstring(n)
---~ if n == 0 then
---~ return "0"
---~ else
---~ local t = { }
---~ while n > 0 do
---~ insert(t,1,n % 2 > 0 and 1 or 0)
---~ n = floor(n/2)
---~ end
---~ return concat(t)
---~ end
---~ end
-
-function number.tobitstring(n,m)
- if n == 0 then
- if m then
- rep("00000000",m)
+ return bits(n, i+1, i, ...)
else
- return "00000000"
+ return bits(n, i+1, ...)
end
else
- local t = { }
- while n > 0 do
- insert(t,1,n % 2 > 0 and 1 or 0)
- n = floor(n/2)
- end
- local nn = 8 - #t % 8
- if nn > 0 and nn < 8 then
- for i=1,nn do
- insert(t,1,0)
- end
- end
- if m then
- m = m * 8 - #t
- if m > 0 then
- insert(t,1,rep("0",m))
- end
- end
- return concat(t)
+ return ...
end
end
---~ print(number.tobitstring(8))
---~ print(number.tobitstring(14))
---~ print(number.tobitstring(66))
---~ print(number.tobitstring(0x00))
---~ print(number.tobitstring(0xFF))
---~ print(number.tobitstring(46260767936,8))
---~ print(#number.tobitstring(46260767936,6))
-
-function number.valid(str,default)
- return tonumber(str) or default or nil
+function number.bits(n)
+ return { bits(n,1) }
end