From 9799147f96fc10a9a70c81f87dfa401b0dbb4c68 Mon Sep 17 00:00:00 2001 From: Ishaan Bhardwaj Date: Mon, 8 Feb 2021 14:53:19 -0500 Subject: [PATCH] Revert "BigInt fixes and optimization (read comments)" Apparently division *still* isn't being handled correctly. This reverts commit 1dda12e4be54413808262cfeac849eb1511fd3f5. --- libs/bigint/bigint.lua | 74 ++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/libs/bigint/bigint.lua b/libs/bigint/bigint.lua index d005e1e..07c1e65 100644 --- a/libs/bigint/bigint.lua +++ b/libs/bigint/bigint.lua @@ -451,17 +451,11 @@ function bigint.exponentiate(big, power) elseif (bigint.compare(exp, bigint.new(1), "==")) then return big else - local result = bigint.new(1) - local base = big:clone() + local result = big:clone() - while (bigint.compare(exp, bigint.new(0), ">")) do - if (bigint.compare( - bigint.modulus(exp, bigint.new(2)), bigint.new(1), "==" - )) then - result = bigint.multiply(result, base) - end - exp = bigint.divide(exp, bigint.new(2)) - base = bigint.multiply(base, base) + while (bigint.compare(exp, bigint.new(1), ">")) do + result = bigint.multiply(result, big) + exp = bigint.subtract(exp, bigint.new(1)) end return result @@ -485,30 +479,54 @@ function bigint.divide_raw(big1, big2) local result = bigint.new() - local dividend = bigint.new() -- Dividend of a single operation + local dividend = bigint.new() -- Dividend of a single operation, not the + -- dividend of the overall function + local divisor = big2:clone() + local factor = 1 - local neg_zero = bigint.new(0) - neg_zero.sign = "-" + -- Walk left to right among digits in the dividend, like in long + -- division + for _, digit in pairs(big1.digits) do + dividend.digits[#dividend.digits + 1] = digit - for i = 1, #big1.digits do - -- Fixes a negative zero bug - if (#dividend.digits ~= 0) and (bigint.compare(dividend, neg_zero, "==")) then - dividend = bigint.new() + -- The dividend is smaller than the divisor, so a zero is appended + -- to the result and the loop ends + if (bigint.compare(dividend, divisor, "<")) then + if (#result.digits > 0) then -- Don't add leading zeroes + result.digits[#result.digits + 1] = 0 + end + else + -- Find the maximum number of divisors that fit into the + -- dividend + factor = 0 + while (bigint.compare(divisor, dividend, "<=")) do + divisor = bigint.add(divisor, big2) + factor = factor + 1 + end + + -- Append the factor to the result + if (factor == 10) then + -- Fixes a weird bug that introduces a new bug if fixed by + -- changing the comparison in the while loop to "<=" + result.digits[#result.digits] = 1 + result.digits[#result.digits + 1] = 0 + else + result.digits[#result.digits + 1] = factor + end + + -- Subtract the divisor from the dividend to obtain the + -- remainder, which is the new dividend for the next loop + dividend = bigint.subtract(dividend, + bigint.subtract(divisor, big2)) + + -- Reset the divisor + divisor = big2:clone() end - table.insert(dividend.digits, big1.digits[i]) - - local factor = 0 - while bigint.compare(dividend, big2, ">=") do - dividend = bigint.subtract(dividend, big2) - factor = factor + 1 - end - - if (factor ~= 0) or (factor == 0 and #result.digits ~= 0) then - table.insert(result.digits, factor) - end end + -- The remainder of the final loop is returned as the function's + -- overall remainder return result, dividend end end