Advertisement
slipers

OpenOS. BIGINT Lib.

Sep 7th, 2018
182
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.57 KB | None | 0 0
  1. -- https://bitbucket.org/tedu/bigintlua/raw/9610654f6d3fe5686e3500fed8aac59eab74edae/bigint.lua -- sources
  2. -- Modified for use in Lua 5.3 (returns a function, and uses math.log rather than math.log10).
  3. --
  4. -- Copyright (c) 2010 Ted Unangst <[email protected]>
  5. --
  6. -- Permission to use, copy, modify, and distribute this software for any
  7. -- purpose with or without fee is hereby granted, provided that the above
  8. -- copyright notice and this permission notice appear in all copies.
  9. --
  10. -- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. -- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. -- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. -- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. -- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. -- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. -- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. --
  18.  
  19. --
  20. -- Lua version ported/copied from the C version, copyright as follows.
  21. --
  22. -- Copyright (c) 2000 by Jef Poskanzer <[email protected]>.
  23. -- All rights reserved.
  24. --
  25. -- Redistribution and use in source and binary forms, with or without
  26. -- modification, are permitted provided that the following conditions
  27. -- are met:
  28. -- 1. Redistributions of source code must retain the above copyright
  29. --    notice, this list of conditions and the following disclaimer.
  30. -- 2. Redistributions in binary form must reproduce the above copyright
  31. --    notice, this list of conditions and the following disclaimer in the
  32. --    documentation and/or other materials provided with the distribution.
  33. --
  34. -- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  35. -- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  36. -- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  37. -- ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  38. -- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  39. -- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  40. -- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  41. -- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  42. -- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  43. -- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  44. -- SUCH DAMAGE.
  45. --
  46.  
  47. --
  48. -- Usage is pretty obvious.  bigint(n) constructs a bigint.  n can be
  49. -- a number or a string.  The regular operators are all overridden via
  50. -- metatable, and also generally work with regular numbers too.
  51. -- Note that comparisons between bigints and numbers *don't* work.
  52. -- bigint() uses a small cache, so bigint(constant) should be fast.
  53. --
  54. -- Only the basic operations are here.  No gcd, factorial, prime test, ...
  55. --
  56. -- Technical notes:
  57. -- Primary difference from the C version is the obvious 1 indexing, this
  58. -- shows up in a variety of ways and places, along with slightly different
  59. -- handling of pre-allocated comps arrays.
  60. -- I made a brief effort to sync some of the comments, but you're better
  61. -- off just reading the C code.
  62. -- C version homepage: http://www.acme.com/software/bigint/
  63. --
  64.  
  65. -- two functions to help make Lua act more like C
  66. local function fl(x)
  67.     if x < 0 then
  68.         return math.ceil(x) + 0 -- make -0 go away
  69.     else
  70.         return math.floor(x)
  71.     end
  72. end
  73.  
  74. local function cmod(a, b)
  75.     local x = a % b
  76.     if a < 0 and x > 0 then
  77.         x = x - b
  78.     end
  79.     return x
  80. end
  81.  
  82.  
  83. local radix = 2^24 -- maybe up to 2^26 is safe?
  84. local radix_sqrt = fl(math.sqrt(radix))
  85.  
  86. local bigintmt -- forward decl
  87. local bigint
  88.  
  89. local function alloc()
  90.     local bi = {}
  91.     setmetatable(bi, bigintmt)
  92.     bi.comps = {}
  93.     bi.sign = 1;
  94.     return bi
  95. end
  96.  
  97. local function clone(a)
  98.     local bi = alloc()
  99.     bi.sign = a.sign
  100.     local c = bi.comps
  101.     local ac = a.comps
  102.     for i = 1, #ac do
  103.         c[i] = ac[i]
  104.     end
  105.     return bi
  106. end
  107.  
  108. local function normalize(bi, notrunc)
  109.     local c = bi.comps
  110.     local v
  111.     -- borrow for negative components
  112.     for i = 1, #c - 1 do
  113.         v = c[i]
  114.         if v < 0 then
  115.             c[i+1] = c[i+1] + fl(v / radix) - 1
  116.             v = cmod(v, radix)
  117.             if v ~= 0 then
  118.                 c[i] = v + radix
  119.             else
  120.                 c[i] = v
  121.                 c[i+1] = c[i+1] + 1
  122.             end
  123.         end
  124.     end
  125.     -- is top component negative?
  126.     if c[#c] < 0 then
  127.         -- switch the sign and fix components
  128.         bi.sign = -bi.sign
  129.         for i = 1, #c - 1 do
  130.             v = c[i]
  131.             c[i] = radix - v
  132.             c[i+1] = c[i+1] + 1
  133.         end
  134.         c[#c] = -c[#c]
  135.     end
  136.     -- carry for components larger than radix
  137.     for i = 1, #c do
  138.         v = c[i]
  139.         if v > radix then
  140.             c[i+1] = (c[i+1] or 0) + fl(v / radix)
  141.             c[i] = cmod(v, radix)
  142.         end
  143.     end
  144.     -- trim off leading zeros
  145.     if not notrunc then
  146.         for i = #c, 2, -1 do
  147.             if c[i] == 0 then
  148.                 c[i] = nil
  149.             else
  150.                 break
  151.             end
  152.         end
  153.     end
  154.     -- check for -0
  155.     if #c == 1 and c[1] == 0 and bi.sign == -1 then
  156.         bi.sign = 1
  157.     end
  158. end
  159.  
  160. local function negate(a)
  161.     local bi = clone(a)
  162.     bi.sign = -bi.sign
  163.     return bi
  164. end
  165.  
  166. local function compare(a, b)
  167.     local ac, bc = a.comps, b.comps
  168.     local as, bs = a.sign, b.sign
  169.     if ac == bc then
  170.         return 0
  171.     elseif as > bs then
  172.         return 1
  173.     elseif as < bs then
  174.         return -1
  175.     elseif #ac > #bc then
  176.         return as
  177.     elseif #ac < #bc then
  178.         return -as
  179.     end
  180.     for i = #ac, 1, -1 do
  181.         if ac[i] > bc[i] then
  182.             return as
  183.         elseif ac[i] < bc[i] then
  184.             return -as
  185.         end
  186.     end
  187.     return 0
  188. end
  189.  
  190. local function lt(a, b)
  191.     return compare(a, b) < 0
  192. end
  193.  
  194. local function eq(a, b)
  195.     return compare(a, b) == 0
  196. end
  197.  
  198. local function le(a, b)
  199.     return compare(a, b) <= 0
  200. end
  201.  
  202. local function addint(a, n)
  203.     local bi = clone(a)
  204.     if bi.sign == 1 then
  205.         bi.comps[1] = bi.comps[1] + n
  206.     else
  207.         bi.comps[1] = bi.comps[1] - n
  208.     end
  209.     normalize(bi)
  210.     return bi
  211. end
  212.  
  213. local function add(a, b)
  214.     if type(a) == "number" then
  215.         return addint(b, a)
  216.     elseif type(b) == "number" then
  217.         return addint(a, b)
  218.     end
  219.     local bi = clone(a)
  220.     local sign = bi.sign == b.sign
  221.     local c = bi.comps
  222.     for i = #c + 1, #b.comps do
  223.         c[i] = 0
  224.     end
  225.     local bc = b.comps
  226.     for i = 1, #bc do
  227.         local v = bc[i]
  228.         if sign then
  229.             c[i] = c[i] + v
  230.         else
  231.             c[i] = c[i] - v
  232.         end
  233.     end
  234.     normalize(bi)
  235.     return bi
  236. end
  237.  
  238. local function sub(a, b)
  239.     if type(b) == "number" then
  240.         return addint(a, -b)
  241.     elseif type(a) == "number" then
  242.         a = bigint(a)
  243.     end
  244.     return add(a, negate(b))
  245. end
  246.  
  247. local function mulint(a, b)
  248.     local bi = clone(a)
  249.     if b < 0 then
  250.         b = -b
  251.         bi.sign = -bi.sign
  252.     end
  253.     local bc = bi.comps
  254.     for i = 1, #bc do
  255.         bc[i] = bc[i] * b
  256.     end
  257.     normalize(bi)
  258.     return bi
  259. end
  260.  
  261. local function multiply(a, b)
  262.     local bi = alloc()
  263.     local c = bi.comps
  264.     local ac, bc = a.comps, b.comps
  265.     for i = 1, #ac + #bc do
  266.         c[i] = 0
  267.     end
  268.     for i = 1, #ac do
  269.         for j = 1, #bc do
  270.             c[i+j-1] = c[i+j-1] + ac[i] * bc[j]
  271.         end
  272.         -- keep the zeroes
  273.         normalize(bi, true)
  274.     end
  275.     normalize(bi)
  276.     if bi ~= bigint(0) then
  277.         bi.sign = a.sign * b.sign
  278.     end
  279.     return bi
  280. end
  281.  
  282. local function kmul(a, b)
  283.     local ac, bc = a.comps, b.comps
  284.     local an, bn = #a.comps, #b.comps
  285.     local bi, bj, bk, bl = alloc(), alloc(), alloc(), alloc()
  286.     local ic, jc, kc, lc = bi.comps, bj.comps, bk.comps, bl.comps
  287.  
  288.     local n = fl((math.max(an, bn) + 1) / 2)
  289.     for i = 1, n do
  290.         ic[i] = (i + n <= an) and ac[i+n] or 0
  291.         jc[i] = (i <= an) and ac[i] or 0
  292.         kc[i] = (i + n <= bn) and bc[i+n] or 0
  293.         lc[i] = (i <= bn) and bc[i] or 0
  294.     end
  295.     normalize(bi)
  296.     normalize(bj)
  297.     normalize(bk)
  298.     normalize(bl)
  299.     local ik = bi * bk
  300.     local jl = bj * bl
  301.     local mid = (bi + bj) * (bk + bl) - ik - jl
  302.     local mc = mid.comps
  303.     local ikc = ik.comps
  304.     local jlc = jl.comps
  305.     for i = 1, #ikc + n*2 do -- fill it up
  306.         jlc[i] = jlc[i] or 0
  307.     end
  308.     for i = 1, #mc do
  309.         jlc[i+n] = jlc[i+n] + mc[i]
  310.     end
  311.     for i = 1, #ikc do
  312.         jlc[i+n*2] = jlc[i+n*2] + ikc[i]
  313.     end
  314.     jl.sign = a.sign * b.sign
  315.     normalize(jl)
  316.     return jl
  317. end
  318.  
  319. local kthresh = 12
  320.  
  321. local function mul(a, b)
  322.     if type(a) == "number" then
  323.         return mulint(b, a)
  324.     elseif type(b) == "number" then
  325.         return mulint(a, b)
  326.     end
  327.     if #a.comps < kthresh or #b.comps < kthresh then
  328.         return multiply(a, b)
  329.     end
  330.     return kmul(a, b)
  331. end
  332.  
  333. local function divint(numer, denom)
  334.     local bi = clone(numer)
  335.     if denom < 0 then
  336.         denom = -denom
  337.         bi.sign = -bi.sign
  338.     end
  339.     local r = 0
  340.     local c = bi.comps
  341.     for i = #c, 1, -1 do
  342.         r = r * radix + c[i]
  343.         c[i] = fl(r / denom)
  344.         r = cmod(r, denom)
  345.     end
  346.     normalize(bi)
  347.     return bi
  348. end
  349.  
  350. local function multi_divide(numer, denom)
  351.     local n = #denom.comps
  352.     local approx = divint(numer, denom.comps[n])
  353.     for i = n, #approx.comps do
  354.         approx.comps[i - n + 1] = approx.comps[i]
  355.     end
  356.     for i = #approx.comps, #approx.comps - n + 2, -1 do
  357.         approx.comps[i] = nil
  358.     end
  359.     local rem = approx * denom - numer
  360.     if rem < denom then
  361.         quotient = approx
  362.     else
  363.         quotient = approx - multi_divide(rem, denom)
  364.     end
  365.     return quotient
  366. end
  367.  
  368. local function multi_divide_wrap(numer, denom)
  369.     -- we use a successive approximation method, but it doesn't work
  370.     -- if the high order component is too small.  adjust if needed.
  371.     if denom.comps[#denom.comps] < radix_sqrt then
  372.         numer = mulint(numer, radix_sqrt)
  373.         denom = mulint(denom, radix_sqrt)
  374.     end
  375.     return multi_divide(numer, denom)
  376. end
  377.  
  378. local function div(numer, denom)
  379.     if type(denom) == "number" then
  380.         if denom == 0 then
  381.             error("divide by 0", 2)
  382.         end
  383.         return divint(numer, denom)
  384.     elseif type(numer) == "number" then
  385.         numer = bigint(numer)
  386.     end
  387.     -- check signs and trivial cases
  388.     local sign = 1
  389.     local cmp = compare(denom, bigint(0))
  390.     if cmp == 0 then
  391.         error("divide by 0", 2)
  392.     elseif cmp == -1 then
  393.         sign = -sign
  394.         denom = negate(denom)
  395.     end
  396.     cmp = compare(numer, bigint(0))
  397.     if cmp == 0 then
  398.         return bigint(0)
  399.     elseif cmp == -1 then
  400.         sign = -sign
  401.         numer = negate(numer)
  402.     end
  403.     cmp = compare(numer, denom)
  404.     if cmp == -1 then
  405.         return bigint(0)
  406.     elseif cmp == 0 then
  407.         return bigint(sign)
  408.     end
  409.     local bi
  410.     -- if small enough, do it the easy way
  411.     if #denom.comps == 1 then
  412.         bi = divint(numer, denom.comps[1])
  413.     else
  414.         bi = multi_divide_wrap(numer, denom)
  415.     end
  416.     if sign == -1 then
  417.         bi = negate(bi)
  418.     end
  419.     return bi
  420. end
  421.  
  422. local function intrem(bi, m)
  423.     if m < 0 then
  424.         m = -m
  425.     end
  426.     local rad_r = 1
  427.     local r = 0
  428.     local bc = bi.comps
  429.     for i = 1, #bc do
  430.         local v = bc[i]
  431.         r = cmod(r + v * rad_r, m)
  432.         rad_r = cmod(rad_r * radix, m)
  433.     end
  434.     if bi.sign < 1 then
  435.         r = -r
  436.     end
  437.     return r
  438. end
  439.  
  440. local function intmod(bi, m)
  441.     local r = intrem(bi, m)
  442.     if r < 0 then
  443.         r = r + m
  444.     end
  445.     return r
  446. end
  447.  
  448. local function rem(bi, m)
  449.     if type(m) == "number" then
  450.         return bigint(intrem(bi, m))
  451.     elseif type(bi) == "number" then
  452.         bi = bigint(bi)
  453.     end
  454.     return bi - ((bi / m) * bi)
  455. end
  456.  
  457. local function mod(a, m)
  458.     local bi = rem(a, m)
  459.     if bi.sign == -1 then
  460.         bi = bi + m
  461.     end
  462.     return bi
  463. end
  464.  
  465. local printscale = 10000000
  466. local printscalefmt = string.format("%%.%dd", math.log(printscale, 10))
  467. local function makestr(bi, s)
  468.     if bi >= bigint(printscale) then
  469.         makestr(divint(bi, printscale), s)
  470.     end
  471.     table.insert(s, string.format(printscalefmt, intmod(bi, printscale)))
  472. end
  473.  
  474. local function biginttostring(bi)
  475.     local s = {}
  476.     if bi < bigint(0) then
  477.         bi = negate(bi)
  478.         table.insert(s, "-")
  479.     end
  480.     makestr(bi, s)
  481.     s = table.concat(s):gsub("^0*", "")
  482.     if s == "" then s = "0" end
  483.     return s
  484. end
  485.  
  486. bigintmt = {
  487.     __add = add,
  488.     __sub = sub,
  489.     __mul = mul,
  490.     __div = div,
  491.     __mod = mod,
  492.     __unm = negate,
  493.     __eq = eq,
  494.     __lt = lt,
  495.     __le = le,
  496.     __tostring = biginttostring
  497. }
  498.  
  499. local cache = {}
  500. local ncache = 0
  501.  
  502. function bigint(n)
  503.     if cache[n] then
  504.         return cache[n]
  505.     end
  506.     local bi
  507.     if type(n) == "string" then
  508.         local digits = { n:byte(1, -1) }
  509.         for i = 1, #digits do
  510.             digits[i] = string.char(digits[i])
  511.         end
  512.         local start = 1
  513.         local sign = 1
  514.         if digits[i] == '-' then
  515.             sign = -1
  516.             start = 2
  517.         end
  518.         bi = bigint(0)
  519.         for i = start, #digits do
  520.             bi = addint(mulint(bi, 10), tonumber(digits[i]))
  521.         end
  522.         bi = mulint(bi, sign)
  523.     else
  524.         bi = alloc()
  525.         bi.comps[1] = n
  526.         normalize(bi)
  527.     end
  528.     if ncache > 100 then
  529.         cache = {}
  530.         ncache = 0
  531.     end
  532.     cache[n] = bi
  533.     ncache = ncache + 1
  534.     return bi
  535. end
  536.  
  537. return bigint
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement