l-number.lua /size: 4588 b    last modification: 2021-10-28 13:50
1if not modules then modules = { } end modules ['l-number'] = {
2    version   = 1.001,
3    comment   = "companion to luat-lib.mkxl",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9local tostring, tonumber = tostring, tonumber
10local format, match, rep = string.format, string.match, string.rep
11local concat, insert = table.concat, table.insert
12local lpegmatch = lpeg.match
13local floor = math.floor
14
15number       = number or { }
16local number = number
17
18-- print(number.tobitstring(8))
19-- print(number.tobitstring(14))
20-- print(number.tobitstring(66))
21-- print(number.tobitstring(0x00))
22-- print(number.tobitstring(0xFF))
23-- print(number.tobitstring(46260767936,4))
24
25if bit32 then
26
27    local bextract = bit32.extract
28
29    local t = {
30        "0", "0", "0", "0", "0", "0", "0", "0",
31        "0", "0", "0", "0", "0", "0", "0", "0",
32        "0", "0", "0", "0", "0", "0", "0", "0",
33        "0", "0", "0", "0", "0", "0", "0", "0",
34    }
35
36    function number.tobitstring(b,m,w)
37        if not w then
38            w = 32
39        end
40        local n = w
41        for i=0,w-1 do
42            local v = bextract(b,i)
43            local k = w - i
44            if v == 1 then
45                n = k
46                t[k] = "1"
47            else
48                t[k] = "0"
49            end
50        end
51        if w then
52            return concat(t,"",1,w)
53        elseif m then
54            m = 33 - m * 8
55            if m < 1 then
56                m = 1
57            end
58            return concat(t,"",1,m)
59        elseif n < 8 then
60            return concat(t)
61        elseif n < 16 then
62            return concat(t,"",9)
63        elseif n < 24 then
64            return concat(t,"",17)
65        else
66            return concat(t,"",25)
67        end
68    end
69
70else
71
72    function number.tobitstring(n,m)
73        if n > 0 then
74            local t = { }
75            while n > 0 do
76                insert(t,1,n % 2 > 0 and 1 or 0)
77                n = floor(n/2)
78            end
79            local nn = 8 - #t % 8
80            if nn > 0 and nn < 8 then
81                for i=1,nn do
82                    insert(t,1,0)
83                end
84            end
85            if m then
86                m = m * 8 - #t
87                if m > 0 then
88                    insert(t,1,rep("0",m))
89                end
90            end
91            return concat(t)
92        elseif m then
93            rep("00000000",m)
94        else
95            return "00000000"
96        end
97    end
98
99end
100
101function number.valid(str,default)
102    return tonumber(str) or default or nil
103end
104
105function number.toevenhex(n)
106    local s = format("%X",n)
107    if #s % 2 == 0 then
108        return s
109    else
110        return "0" .. s
111    end
112end
113
114-- -- a,b,c,d,e,f = number.toset(100101)
115-- --
116-- -- function number.toset(n)
117-- --     return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
118-- -- end
119-- --
120-- -- -- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
121-- -- -- on
122-- --
123-- -- for i=1,1000000 do
124-- --     local a,b,c,d,e,f,g,h = number.toset(12345678)
125-- --     local a,b,c,d         = number.toset(1234)
126-- --     local a,b,c           = number.toset(123)
127-- --     local a,b,c           = number.toset("123")
128-- -- end
129--
130-- local one = lpeg.C(1-lpeg.S('')/tonumber)^1
131--
132-- function number.toset(n)
133--     return lpegmatch(one,tostring(n))
134-- end
135--
136-- -- function number.bits(n,zero)
137-- --     local t, i = { }, (zero and 0) or 1
138-- --     while n > 0 do
139-- --         local m = n % 2
140-- --         if m > 0 then
141-- --             insert(t,1,i)
142-- --         end
143-- --         n = floor(n/2)
144-- --         i = i + 1
145-- --     end
146-- --     return t
147-- -- end
148-- --
149-- -- -- a bit faster
150--
151-- local function bits(n,i,...)
152--     if n > 0 then
153--         local m = n % 2
154--         local n = floor(n/2)
155--         if m > 0 then
156--             return bits(n, i+1, i, ...)
157--         else
158--             return bits(n, i+1,    ...)
159--         end
160--     else
161--         return ...
162--     end
163-- end
164--
165-- function number.bits(n)
166--     return { bits(n,1) }
167-- end
168
169function number.bytetodecimal(b)
170    local d = floor(b * 100 / 255 + 0.5)
171    if d > 100 then
172        return 100
173    elseif d < -100 then
174        return -100
175    else
176        return d
177    end
178end
179
180function number.decimaltobyte(d)
181    local b = floor(d * 255 / 100 + 0.5)
182    if b > 255 then
183        return 255
184    elseif b < -255 then
185        return -255
186    else
187        return b
188    end
189end
190
191function number.idiv(i,d)
192    return floor(i/d) -- i//d in 5.3
193end
194