Advertisement
blunty666

bigInt

Feb 11th, 2016
339
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 17.05 KB | None | 0 0
  1. local littleBASE = 2
  2. local base_exponent = 25
  3. local BASE = littleBASE^base_exponent
  4. local BASE_LEN = math.ceil(math.log10(BASE))
  5.  
  6. local ZERO, ONE, TWO
  7.  
  8. --===== MAIN ARITHMETIC METHODS =====--
  9. function add(x, y)
  10.     if x == nil or y == nil then
  11.         error("bigInt add: missing parameter")
  12.     elseif x.isBig ~= true or y.isBig ~= true then
  13.         error("bigInt add: invalid parameter")
  14.     elseif not x.sign and y.sign then
  15.         y.sign = not y.sign
  16.         local ans = sub(x, y)
  17.         y.sign = not y.sign
  18.         return ans
  19.     elseif x.sign and not y.sign then
  20.         x.sign = not x.sign
  21.         local ans = sub(y, x)
  22.         x.sign = not x.sign
  23.         return ans
  24.     elseif x.sign and y.sign then
  25.         x.sign, y.sign = not x.sign, not y.sign
  26.         local ans = -add(x, y)
  27.         x.sign = not x.sign
  28.         y.sign = not y.sign
  29.         return ans
  30.     end
  31.     local ans = new()
  32.     local carry = 0
  33.     for i = 0, math.max(#x, #y) do
  34.         ans[i] = (x[i] or 0) + (y[i] or 0) + carry
  35.         if ans[i] >= BASE then
  36.             ans[i] = ans[i] - BASE
  37.             carry = 1
  38.         else
  39.             carry = 0
  40.         end
  41.     end
  42.     ans[math.max(#x, #y) + 1] = carry
  43.     removeZeroes(ans)
  44.     return ans
  45. end
  46.  
  47. function sub(x, y)
  48.     if x == nil or y == nil then
  49.         error("bigInt sub: missing parameter")
  50.     elseif x.isBig ~= true or y.isBig ~= true then
  51.         error("bigInt sub: invalid parameter")
  52.     elseif not x.sign and y.sign then
  53.         y.sign = not y.sign
  54.         local ans = add(x, y)
  55.         y.sign = not y.sign
  56.         return ans
  57.     elseif x.sign and not y.sign then
  58.         x.sign = not x.sign
  59.         local ans = -add(x, y)
  60.         x.sign = not x.sign
  61.         return ans
  62.     elseif x.sign and y.sign then
  63.         x.sign, y.sign = not x.sign, not y.sign
  64.         local ans = sub(y, x)
  65.         x.sign = not x.sign
  66.         y.sign = not y.sign
  67.         return ans
  68.     elseif compareAbs(x, y) == -1 then
  69.         return -sub(y, x)
  70.     end
  71.     local ans = new()
  72.     local carry = 0
  73.     for i = 0, #x do
  74.         ans[i] = (x[i] or 0) - (y[i] or 0) - carry
  75.         if ans[i] < 0 then
  76.             ans[i] = ans[i] + BASE
  77.             carry = 1
  78.         else
  79.             carry = 0
  80.         end
  81.     end
  82.     removeZeroes(ans)
  83.     return ans
  84. end
  85.  
  86. function mul(x, y)
  87.     if x == nil or y == nil then
  88.         error("bigInt mul: missing parameter")
  89.     elseif x.isBig ~= true or y.isBig ~= true then
  90.         error("bigInt mul: invalid parameter")
  91.     elseif x.sign and not y.sign then
  92.         x.sign = not x.sign
  93.         local ans = -mul(x, y)
  94.         x.sign = not x.sign
  95.         return ans
  96.     elseif not x.sign and y.sign then
  97.         y.sign = not y.sign
  98.         local ans = -mul(x, y)
  99.         y.sign = not y.sign
  100.         return ans
  101.     elseif x.sign and y.sign then
  102.         x.sign, y.sign = not x.sign, not y.sign
  103.         local ans = mul(x, y)
  104.         x.sign, y.sign = not x.sign, not y.sign
  105.         return ans
  106.     end
  107.     local ans = new()
  108.     local carry = 0
  109.     local temp = 0
  110.     for i = 0, #y do
  111.         carry = 0
  112.         for j = 0, #x do
  113.             temp = (ans[i + j] or 0) + (x[j]*y[i]) + carry
  114.             ans[i + j] = temp % BASE
  115.             carry = math.floor(temp/BASE)
  116.         end
  117.         ans[i + #x + 1] = carry
  118.     end
  119.     removeZeroes(ans)
  120.     return ans
  121. end
  122.  
  123. function div(x, y)
  124.     if x == nil or y == nil then
  125.         error("bigInt div: missing parameter")
  126.     elseif x.isBig ~= true or y.isBig ~= true then
  127.         error("bigInt div: invalid parameter")
  128.     elseif compareAbs(y, ZERO) == 0 then
  129.         error("bigInt div: attempt to divide by zero")
  130.     elseif not x.sign and y.sign then
  131.         y.sign = not y.sign
  132.         local quot, rem = div(x, y)
  133.         y.sign = not y.sign
  134.         return -quot, rem
  135.     elseif x.sign and not y.sign then
  136.         x.sign = not x.sign
  137.         local quot, rem = div(x, y)
  138.         x.sign = not x.sign
  139.         if compare(rem, ZERO) == -1 then
  140.             quot = add(quot, ONE)
  141.             rem = sub(y, rem)
  142.         end
  143.         return -quot, rem
  144.     elseif x.sign and y.sign then
  145.         x.sign, y.sign = not x.sign, not y.sign
  146.         local quot, rem = div(x, y)
  147.         if compare(rem, ZERO) == -1 then
  148.             quot = add(quot, ONE)
  149.             rem = sub(y, rem)
  150.         end
  151.         x.sign, y.sign = not x.sign, not y.sign
  152.         return quot, rem
  153.     elseif #x == 0 and #y == 0 then
  154.         return new(math.floor(x[0]/y[0])), new(x[0] % y[0])
  155.     elseif compareAbs(x, y) == -1 then
  156.         return new(), copy(x)
  157.     end
  158.    
  159.     --Normalisation
  160.     local scaledY = copy(y)
  161.     local scaledX = copy(x)
  162.     local lambda = 0
  163.     while scaledY[#scaledY] < BASE/littleBASE do
  164.         lambda = lambda + 1
  165.         left_shift(scaledY, 1)
  166.         left_shift(scaledX, 1)
  167.     end
  168.     --Step 1
  169.     local n, t = #scaledX, #scaledY
  170.     local quot = alloc(n - t)
  171.  
  172.     --Step 2
  173.     local tempY = copy(scaledY)
  174.     shift_base(tempY, n - t)
  175.     while compare(scaledX, tempY) ~= -1 do
  176.         quot[n - t] = quot[n - t] + 1
  177.         scaledX = sub(scaledX, tempY)
  178.     end
  179.  
  180.     --Step 3
  181.     local topY = new()
  182.     topY[1] = scaledY[t]
  183.     topY[0] = scaledY[t - 1] or 0
  184.     local tempX = new()
  185.     for i = n, t + 1, -1 do
  186.    
  187.         os.queueEvent("bigInt_yield")
  188.         os.pullEvent()
  189.  
  190.         tempX[2] = scaledX[i] or 0
  191.         tempX[1] = scaledX[i - 1] or 0
  192.         tempX[0] = scaledX[i - 2] or 0
  193.  
  194.         --Step 3.1
  195.         if tempX[2] == scaledY[t] then
  196.             quot[i - t - 1] = BASE - 1
  197.         else
  198.             quot[i - t - 1] = math.floor((tempX[2]*BASE + tempX[1])/scaledY[t])
  199.         end
  200.  
  201.         --Step 3.2
  202.         local step = 0
  203.         while compare(mul(topY, new(quot[i - t - 1])), tempX) == 1 do
  204.             step = step + 1
  205.             quot[i - t - 1] = quot[i - t - 1] - 1
  206.         end
  207.  
  208.         --Step 3.3
  209.         tempY = copy(scaledY)
  210.         shift_base(tempY, i - t - 1)
  211.         scaledX = sub(scaledX, mul(tempY, new(quot[i - t - 1])))
  212.  
  213.         --Step 3.4
  214.         if compare(scaledX, ZERO) == -1 then
  215.             scaledX = add(scaledX, tempY)
  216.             quot[i - t - 1] = quot[i - t - 1] - 1
  217.         end
  218.     end
  219.  
  220.     if lambda > 0 then
  221.         right_shift(scaledX, lambda)
  222.     end
  223.  
  224.     removeZeroes(quot)
  225.     removeZeroes(scaledX)
  226.  
  227.     return quot, scaledX
  228. end
  229.  
  230. function pow(x, y)
  231.     if x == nil or y == nil then
  232.         error("bigInt pow: missing parameter")
  233.     elseif x.isBig ~= true or y.isBig ~= true then
  234.         error("bigInt pow: invalid parameter")
  235.     elseif compareAbs(y, ZERO) == -1 then
  236.         error("bigInt pow: negative exponent not allowed")
  237.     elseif compareAbs(y, ZERO) == 0 then
  238.         return new(1)
  239.     elseif compareAbs(y, ONE) == 0 then
  240.         return new(x)
  241.     end
  242.     local n = copy(y)
  243.     local z = copy(x)
  244.     local w = new(1)
  245.     while true do
  246.         if n[0] % 2 == 0 then
  247.             right_shift(n, 1)
  248.         else
  249.             right_shift(n, 1, true)
  250.             w = mul(z, w)
  251.             if compareAbs(n, ZERO) == 0 then
  252.                 return w
  253.             end
  254.         end
  255.         z = square(z)
  256.     end
  257. end
  258.  
  259. --===== OTHER ARITHMETIC METHODS =====--
  260. function abs(x)
  261.     local bNum1 = new(x)
  262.     bNum1.sign = false
  263.     return bNum1
  264. end
  265.  
  266. function square(x)
  267.     if x == nil then
  268.         error("bigInt square: missing parameter")
  269.     elseif type(x) ~= "table" or not x.isBig then
  270.         error("bigInt square: invalid parameter")
  271.     end
  272.  
  273.     local ans = alloc(#x*2 + 1)
  274.     local carry = 0
  275.     local temp = 0
  276.     for i = 0, #x do
  277.         temp = ans[2*i] + x[i]*x[i]
  278.         ans[2*i] = temp % BASE
  279.         carry = math.floor(temp/BASE)
  280.         for j = i + 1, #x do
  281.             temp = ans[i + j] + 2*x[j]*x[i] + carry
  282.             ans[i + j] = temp % BASE
  283.             carry = math.floor(temp/BASE)
  284.         end
  285.         ans[i + #x + 1] = carry
  286.     end
  287.     removeZeroes(ans)
  288.     return ans
  289. end
  290.  
  291. function gcd(x, y)
  292.     if x == nil or y == nil then
  293.         error("bigInt gcd: missing parameter")
  294.     elseif type(x) ~= "table" or x.isBig ~= true or type(y) ~= "table" or y.isBig ~= true then
  295.         error("bigInt gcd: invalid parameter")
  296.     elseif compareAbs(x, y) == -1 then
  297.         return gcd(y, x)
  298.     end
  299.  
  300.     local g = new(1)
  301.     local tempX = copy(x)
  302.     local tempY = copy(y)
  303.  
  304.     while tempX[0] % 2 == 0 and tempY[0] % 2 == 0 do
  305.         right_shift(tempX, 1)
  306.         right_shift(tempY, 1)
  307.         left_shift(g, 1)
  308.     end
  309.  
  310.     while compareAbs(tempX, ZERO) ~= 0 do
  311.         while tempX[0] % 2 == 0 do
  312.             right_shift(tempX, 1)
  313.         end
  314.         while tempY[0] % 2 == 0 do
  315.             right_shift(tempY, 1)
  316.         end
  317.         local t = sub(tempX, tempY)
  318.         t.sign = false
  319.         right_shift(t, 1)
  320.         if compare(tempX, tempY) == -1 then
  321.             tempY = t
  322.         else
  323.             tempX = t
  324.         end
  325.     end
  326.  
  327.     return mul(g, tempY)
  328. end
  329.  
  330. function egcd(x, y)
  331.     if x == nil or y == nil then
  332.         error("bigInt egcd: missing parameter")
  333.     elseif type(x) ~= "table" or x.isBig ~= true or type(y) ~= "table" or y.isBig ~= true then
  334.         error("bigInt egcd: invalid parameter")
  335.     end
  336.  
  337.     local g = new(1)
  338.     local tempX = copy(x)
  339.     local tempY = copy(y)
  340.     tempX.sign = false 
  341.     tempY.sign = false
  342.  
  343.     while tempX[0] % 2 == 0 and tempY[0] % 2 == 0 do
  344.         right_shift(tempX, 1)
  345.         right_shift(tempY, 1)
  346.         left_shift(g, 1)
  347.     end
  348.  
  349.     local u = copy(tempX)
  350.     local v = copy(tempY)
  351.     local A = new(1)
  352.     local B = new()
  353.     local C = new()
  354.     local D = new(1)
  355.     repeat
  356.         while u[0] % 2 == 0 do
  357.             right_shift(u, 1)
  358.             if A[0] % 2 ~= 0 or B[0] % 2 ~= 0 then
  359.                 A = add(A, tempY)
  360.                 B = sub(B, tempX)
  361.             end
  362.             right_shift(A, 1, true)
  363.             right_shift(B, 1, true)
  364.         end
  365.         while v[0] % 2 == 0 do
  366.             right_shift(v, 1)
  367.             if C[0] % 2 ~= 0 or D[0] % 2 ~= 0 then
  368.                 C = add(C, tempY)
  369.                 D = sub(D, tempX)
  370.             end
  371.             right_shift(C, 1, true)
  372.             right_shift(D, 1, true)
  373.         end
  374.         if compare(u, v) ~= -1 then
  375.             u = sub(u, v)
  376.             A = sub(A, C)
  377.             B = sub(B, D)
  378.         else
  379.             v = sub(v, u)
  380.             C = sub(C, A)
  381.             D = sub(D, B)
  382.         end
  383.     until compareAbs(u, ZERO) == 0
  384.     return C, D, mul(g, v)
  385. end
  386.  
  387. function powMod(x, y, m)
  388.     local n = copy(y)
  389.     local z = copy(x)
  390.     local w = new(1)
  391.     while true do
  392.         if n[0] % 2 == 0 then
  393.             right_shift(n, 1)
  394.         else
  395.             right_shift(n, 1, true)
  396.             w = mul(z, w) % m
  397.             if compareAbs(n, ZERO) == 0 then
  398.                 return w
  399.             end
  400.         end
  401.         z = square(z) % m
  402.     end
  403. end
  404.  
  405. --===== BITWISE METHODS =====--
  406. function left_shift(x, n)
  407.     if x == nil then
  408.         error("bigInt left_shift: parameter missing")
  409.     elseif type(x) == "table" and x.isBig == true then
  410.         for i = 1, n do
  411.             local carry = 0
  412.             local temp = 0
  413.             for i = 0, #x do
  414.                 temp = x[i]*littleBASE
  415.                 x[i] = (temp % BASE) + carry
  416.                 carry = math.floor(temp/BASE)
  417.             end
  418.             if carry > 0 then
  419.                 table.insert(x, carry)
  420.             end
  421.         end
  422.     else
  423.         error("bigInt left_shift: invalid parameter")
  424.     end
  425. end
  426.  
  427. function right_shift(x, n, noWarn)
  428.     if x == nil then
  429.         error("bigInt right_shift: parameter missing")
  430.     elseif type(x) == "table" and x.isBig == true then
  431.         for j = 1, n do
  432.             local carry = 0
  433.             local temp = 0
  434.             for i = #x, 0, -1 do
  435.                 temp = x[i]
  436.                 x[i] = math.floor(temp/littleBASE) + (carry*BASE)/littleBASE
  437.                 carry = temp % littleBASE
  438.             end
  439.             if carry > 0 and noWarn ~= true then
  440.                 error("bigInt right_shift: carry left over", 2)
  441.             end
  442.         end
  443.         removeZeroes(x)
  444.     else
  445.         error("bigInt right_shift: invalid parameter")
  446.     end
  447. end
  448.  
  449. function shift_base(x, n)
  450.     if x == nil then
  451.         error("bigInt shift_base: parameter missing")
  452.     elseif type(x) == "table" and x.isBig == true then
  453.         if n > 0 then
  454.             for i = #x + n, 0, -1 do
  455.                 x[i] = x[i - n] or 0
  456.             end
  457.         elseif n < 0 then
  458.             for i = 0, #x do
  459.                 x[i] = x[i - n] or 0
  460.             end
  461.         end
  462.         removeZeroes(x)
  463.     else
  464.         error("bigInt shift_base: invalid parameter")
  465.     end
  466. end
  467.  
  468. --===== RELATIONAL METHODS =====--
  469. function compareAbs(x, y)
  470.     if x == nil or y == nil then
  471.         error("bigInt compareAbs: missing parameter")
  472.     elseif type(x) == "table" and x.isBig == true and type(y) == "table" and y.isBig == true then
  473.         if #x > #y then
  474.             return 1
  475.         elseif #x < #y then
  476.             return -1
  477.         else
  478.             for i = #x, 0, -1 do
  479.                 if x[i] > y[i] then
  480.                     return 1
  481.                 elseif x[i] < y[i] then
  482.                     return -1
  483.                 end
  484.             end
  485.         end
  486.         return 0
  487.     else
  488.         error("bigInt compareAbs: invalid parameter")
  489.     end
  490. end
  491.  
  492. function compare(x, y)
  493.     if x == nil or y == nil then
  494.         error("bigInt compare: missing parameter")
  495.     elseif type(x) == "table" and x.isBig == true and type(y) == "table" and y.isBig == true then
  496.         if not x.sign and y.sign then
  497.             return 1
  498.         elseif x.sign and not y.sign then
  499.             return -1
  500.         elseif x.sign and y.sign then
  501.             return -compareAbs(x, y)
  502.         else
  503.             return compareAbs(x, y)
  504.         end
  505.     else
  506.         error("bigInt compare: invalid parameter")
  507.     end
  508. end
  509.  
  510. --===== MISC METHODS =====--
  511. function tostring(bNum)
  512.     if type(bNum) == "table" and bNum.isBig then
  513.         if compareAbs(bNum, ZERO) == 0 then
  514.             return "0"
  515.         end
  516.         local temp = ""
  517.         local tempN = copy(bNum)
  518.         local tempM
  519.         local modulus = new(10^(BASE_LEN - 1))
  520.         while compareAbs(tempN, ZERO) ~= 0 do
  521.             os.queueEvent("bigInt_yield")
  522.             os.pullEvent()
  523.             tempN, tempM = div(tempN, modulus)
  524.             if tempM[0] then
  525.                 local a = tempM[0]
  526.                 local temp1 = ""
  527.                 if string.len(a) < BASE_LEN - 1 then
  528.                     temp1 = string.rep("0", BASE_LEN - 1 - string.len(a))
  529.                 end
  530.                 local temp2 = a
  531.                 temp = temp1..temp2..temp
  532.             else
  533.                 temp = string.rep("0", BASE_LEN - 1)..temp
  534.             end
  535.         end
  536.         while string.sub(temp, 1, 1) == "0" do
  537.             temp = string.sub(temp, 2)
  538.         end
  539.         if bNum.sign then
  540.             temp = "-"..temp
  541.         end
  542.         return temp
  543.     end
  544. end
  545.  
  546. function removeZeroes(bNum)
  547.     if bNum == nil then
  548.         error("bigInt removeZeroes: missing parameter")
  549.     elseif type(bNum) == "table" and bNum.isBig == true then
  550.         for i = #bNum, 1, -1 do
  551.             if bNum[i] == 0 then
  552.                 bNum[i] = nil
  553.             else
  554.                 break
  555.             end
  556.         end
  557.     else
  558.         error("bigInt removeZeroes: invalid parameter")
  559.     end
  560. end
  561.  
  562. function change(x, y)
  563.     if x == nil or y == nil then
  564.         error("bigInt change: missing parameter", 3)
  565.     elseif type(x) == "table" and x.isBig == true and type(y) == "table" and y.isBig == true then
  566.         for i = 0, #y do
  567.             x[i] = y[i]
  568.         end
  569.         for i = #y + 1, #x do
  570.             x[i] = nil
  571.         end
  572.         x.sign = y.sign
  573.     else
  574.         error("bigInt change: invalid parameter", 3)
  575.     end
  576. end
  577.  
  578. function copy(x)
  579.     local temp = new()
  580.     change(temp, x)
  581.     return temp
  582. end
  583.  
  584. function alloc(n)
  585.     local temp = new()
  586.     for i = 0, n do
  587.         temp[i] = 0
  588.     end
  589.     return temp
  590. end
  591.  
  592. function serialise(a)
  593.     local out = ""
  594.     for i = 0, #a do
  595.         out = out..":"..a[i]
  596.     end
  597.     if a.sign then
  598.         out = "-"..out
  599.     end
  600.     return out
  601. end
  602.  
  603. function unserialise(a)
  604.     local out = new()
  605.     if string.sub(a, 1, 1) == "-" then
  606.         out.sign = true
  607.     end
  608.    
  609.     local size = 0
  610.     local word, seek = string.match(a, ":([^:]+)()", 1)
  611.     while word do
  612.         out[size] = tonumber(word)
  613.         size = size + 1
  614.         word, seek = string.match(a, ":([^:]+)()", seek)
  615.     end
  616.    
  617.     return out
  618. end
  619.  
  620. --===== PRIME NUMBER GENERATION =====--
  621. function randKBitInt(k)
  622.     local fullWords = math.floor(k/base_exponent)
  623.     local lastWord = k % base_exponent
  624.     local ans = alloc(fullWords)
  625.     for i = 0, fullWords - 1 do
  626.         ans[i] = math.random(0, BASE - 1)
  627.     end
  628.     ans[#ans] = math.random(math.floor(2^(lastWord - 1)), math.max(0, 2^lastWord - 1))
  629.     return ans
  630. end
  631.  
  632. function millerRabin(n, t)
  633.     local r = n - 1
  634.     local s = 0
  635.     while r[0] % 2 == 0 do
  636.         right_shift(r, 1)
  637.         s = s + 1
  638.     end
  639.     local nMinusOne = n - 1
  640.     local isFirstPass = true
  641.     for i = 1, t do
  642.         os.queueEvent("bigInt_yield")
  643.         os.pullEvent()
  644.         local a
  645.         if isFirstPass then
  646.             a = new(2)
  647.             isFirstPass = false
  648.         else
  649.             repeat
  650.                 a = copy(n) - 2
  651.                 right_shift(a, 1, true)
  652.                 a = a + math.random(-1000, 1000)
  653.             until TWO <= a and a <= n - 2
  654.         end
  655.         local y = powMod(a, r, n)
  656.         if y ~= ONE and y ~= nMinusOne then
  657.             local j = 1
  658.             while j <= s - 1 and y ~= nMinusOne do
  659.                 os.queueEvent("bigInt_yield")
  660.                 os.pullEvent()
  661.                 y = square(y) % n
  662.                 if y == ONE then
  663.                     return false
  664.                 end
  665.                 j = j + 1
  666.             end
  667.             if y ~= nMinusOne then
  668.                 return false
  669.             end
  670.         end
  671.     end
  672.     return true
  673. end
  674.  
  675. local rounds = {
  676.     {150, 18},
  677.     {200, 15},
  678.     {250, 12},
  679.     {300, 9},
  680.     {350, 8},
  681.     {400, 7},
  682.     {450, 6},
  683.     {550, 5},
  684.     {650, 4},
  685.     {850, 3},
  686.     {1300, 2},
  687. }
  688.  
  689. function kBitPrime(bitLength)
  690.     local millerRabinRounds = 27
  691.     for i = 1, #rounds do
  692.         if bitLength < rounds[i][1] then
  693.             break
  694.         else
  695.             millerRabinRounds = rounds[i][2]
  696.         end
  697.     end
  698.     local isPrime, number = false, nil
  699.     repeat
  700.         number = randKBitInt(bitLength)
  701.         if number[0] == 0 then
  702.             number[0] = 1
  703.         elseif number[0] % 2 == 0 then
  704.             number[0] = number[0] - 1
  705.         end
  706.         isPrime = millerRabin(number, millerRabinRounds)
  707.     until isPrime
  708.     return number
  709. end
  710.  
  711. --===== METATABLES =====--
  712. local bigIntMethods = {
  713.     abs = abs,
  714.     gcd = gcd,
  715.     egcd = egcd,
  716.     powMod = powMod,
  717.     left_shift = left_shift,
  718.     right_shift = right_shift,
  719.     shift_base = shift_base,
  720.     copy = copy,
  721.     serialise = serialise,
  722. }
  723. local bigIntMetatable = {
  724.     __index = bigIntMethods,
  725.  
  726.     __add = function(x, y)
  727.         return add(new(x), new(y))
  728.     end,
  729.     __sub = function(x, y)
  730.         return sub(new(x), new(y))
  731.     end,
  732.     __mul = function(x, y)
  733.         return mul(new(x), new(y))
  734.     end,
  735.     __div = function(x, y)
  736.         local quot = div(new(x), new(y))
  737.         return quot
  738.     end,
  739.     __mod = function(x, y)
  740.         local _, rem = div(new(x), new(y))
  741.         return rem
  742.     end,
  743.     __pow = function(x, y)
  744.         return pow(new(x), new(y))
  745.     end,
  746.     __unm = function(x)
  747.         local y = new(x)
  748.         y.sign = not y.sign
  749.         return y
  750.     end,
  751.  
  752.     __eq = function(x, y)
  753.         return compare(new(x), new(y)) == 0
  754.     end,
  755.     __lt = function(x, y)
  756.         return compare(new(x), new(y)) == -1
  757.     end,
  758.     __le = function(x, y)
  759.         return compare(new(x), new(y)) < 1
  760.     end,
  761.    
  762.     __tostring = tostring,
  763. }
  764.  
  765. function new(num)
  766.     local bNum = {}
  767.     setmetatable(bNum, bigIntMetatable)
  768.     if num == nil then
  769.         bNum[0] = 0
  770.         bNum.sign = false
  771.     elseif type(num) == "table" then
  772.         if num.isBig == true then
  773.             return copy(num)
  774.         end
  775.     elseif type(num) == "number" and math.abs(num) ~= math.huge then
  776.         if num < 0 then
  777.             bNum.sign = true
  778.         else
  779.             bNum.sign = false
  780.         end
  781.         local temp = math.abs(num)
  782.         if temp == 0 then
  783.             bNum[0] = 0
  784.         else
  785.             local i = 0
  786.             while temp > 0 do
  787.                 bNum[i] = temp % BASE
  788.                 i = i + 1
  789.                 temp = math.floor(temp/BASE)
  790.             end
  791.         end
  792.     else
  793.         error("bigInt new: invalid parameter")
  794.     end
  795.     bNum.isBig = true
  796.     return bNum
  797. end
  798.  
  799. ZERO, ONE, TWO = new(0), new(1), new(2)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement