Skip to content

Commit 2fcd2c3

Browse files
committed
Support integer truncate division and modulo operations
1 parent bab493a commit 2fcd2c3

File tree

3 files changed

+193
-3
lines changed

3 files changed

+193
-3
lines changed

bint.lua

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ local BINT_SIZE = BINT_BITS // BINT_WORDBITS
163163
local BINT_WORDMAX = (1 << BINT_WORDBITS) - 1
164164
local BINT_WORDMSB = (1 << (BINT_WORDBITS - 1))
165165
local BINT_MATHMININTEGER, BINT_MATHMAXINTEGER
166+
local BINT_MININTEGER
166167

167168
-- Create a new bint without initializing.
168169
local function bint_newempty()
@@ -1191,6 +1192,56 @@ function bint.umod(x, y)
11911192
return rema
11921193
end
11931194

1195+
--- Perform integer truncate division and modulo operation between two numbers considering bints.
1196+
-- This is effectively the same of @{bint.__tdiv} and @{bint.__tmod}.
1197+
-- @param x The numerator, a bint or lua number.
1198+
-- @param y The denominator, a bint or lua number.
1199+
-- @return The quotient following the remainder, both bint or lua number.
1200+
-- @raise Asserts on attempt to divide by zero or on division overflow.
1201+
-- @see bint.__tdiv
1202+
-- @see bint.__tmod
1203+
function bint.tdivmod(x, y)
1204+
local ax, ay = bint.abs(x), bint.abs(y)
1205+
local ix, iy = bint.tobint(ax), bint.tobint(ay)
1206+
local quot, rema
1207+
if ix and iy then
1208+
assert(not (bint.eq(x, BINT_MININTEGER) and bint.isminusone(y)), 'division overflow')
1209+
quot, rema = bint.udivmod(ix, iy)
1210+
else
1211+
quot, rema = ax // ay, ax % ay
1212+
end
1213+
local isxneg, isyneg = bint.isneg(x), bint.isneg(y)
1214+
if isxneg ~= isyneg then
1215+
quot = -quot
1216+
end
1217+
if isxneg then
1218+
rema = -rema
1219+
end
1220+
return quot, rema
1221+
end
1222+
1223+
--- Perform truncate division between two numbers considering bints.
1224+
-- Truncate division is a division that rounds the quotient towards zero.
1225+
-- @param x The numerator, a bint or lua number.
1226+
-- @param y The denominator, a bint or lua number.
1227+
-- @return The quotient, a bint or lua number.
1228+
-- @raise Asserts on attempt to divide by zero or on division overflow.
1229+
function bint.tdiv(x, y)
1230+
return (bint.tdivmod(x, y))
1231+
end
1232+
1233+
--- Perform integer truncate modulo operation between two numbers considering bints.
1234+
-- The operation is defined as the remainder of the truncate division
1235+
-- (division that rounds the quotient towards zero).
1236+
-- @param x The numerator, a bint or lua number.
1237+
-- @param y The denominator, a bint or lua number.
1238+
-- @return The remainder, a bint or lua number.
1239+
-- @raise Asserts on attempt to divide by zero or on division overflow.
1240+
function bint.tmod(x, y)
1241+
local _, rema = bint.tdivmod(x, y)
1242+
return rema
1243+
end
1244+
11941245
--- Perform integer floor division and modulo operation between two numbers considering bints.
11951246
-- This is effectively the same of @{bint.__idiv} and @{bint.__mod}.
11961247
-- @param x The numerator, a bint or lua number.
@@ -1612,6 +1663,7 @@ setmetatable(bint, {
16121663
})
16131664

16141665
BINT_MATHMININTEGER, BINT_MATHMAXINTEGER = bint.new(math.mininteger), bint.new(math.maxinteger)
1666+
BINT_MININTEGER = bint.mininteger()
16151667
memo[memoindex] = bint
16161668

16171669
return bint

docs/index.html

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ <h2>Usage</h2>
121121
</ul>
122122

123123
<p>To output a very large integer with no loss you probably want to use <a href="index.html#tobase">bint.tobase</a>
124-
or call <a href="https://www.lua.org/manual/5.3/manual.html#pdf-tostring">tostring</a> to get a string representation.</p>
124+
or call <a href="https://www.lua.org/manual/5.1/manual.html#pdf-tostring">tostring</a> to get a string representation.</p>
125125

126126
<h2>Precautions</h2>
127127

@@ -352,6 +352,18 @@ <h2><a href="#Functions">Functions</a></h2>
352352
<td class="summary">Perform unsigned integer modulo operation between two integers considering bints.</td>
353353
</tr>
354354
<tr>
355+
<td class="name" nowrap><a href="#tdivmod">tdivmod (x, y)</a></td>
356+
<td class="summary">Perform integer truncate division and modulo operation between two numbers considering bints.</td>
357+
</tr>
358+
<tr>
359+
<td class="name" nowrap><a href="#tdiv">tdiv (x, y)</a></td>
360+
<td class="summary">Perform truncate division between two numbers considering bints.</td>
361+
</tr>
362+
<tr>
363+
<td class="name" nowrap><a href="#tmod">tmod (x, y)</a></td>
364+
<td class="summary">Perform integer truncate modulo operation between two numbers considering bints.</td>
365+
</tr>
366+
<tr>
355367
<td class="name" nowrap><a href="#idivmod">idivmod (x, y)</a></td>
356368
<td class="summary">Perform integer floor division and modulo operation between two numbers considering bints.</td>
357369
</tr>
@@ -1661,6 +1673,103 @@ <h3>Raises:</h3>
16611673

16621674

16631675

1676+
</dd>
1677+
<dt>
1678+
<a name = "tdivmod"></a>
1679+
<strong>tdivmod (x, y)</strong>
1680+
</dt>
1681+
<dd>
1682+
Perform integer truncate division and modulo operation between two numbers considering bints.
1683+
This is effectively the same of ??? and ???.
1684+
1685+
1686+
<h3>Parameters:</h3>
1687+
<ul>
1688+
<li><span class="parameter">x</span>
1689+
The numerator, a bint or lua number.
1690+
</li>
1691+
<li><span class="parameter">y</span>
1692+
The denominator, a bint or lua number.
1693+
</li>
1694+
</ul>
1695+
1696+
<h3>Returns:</h3>
1697+
<ol>
1698+
1699+
The quotient following the remainder, both bint or lua number.
1700+
</ol>
1701+
1702+
<h3>Raises:</h3>
1703+
Asserts on attempt to divide by zero or on division overflow.
1704+
1705+
<h3>See also:</h3>
1706+
<ul>
1707+
</ul>
1708+
1709+
1710+
</dd>
1711+
<dt>
1712+
<a name = "tdiv"></a>
1713+
<strong>tdiv (x, y)</strong>
1714+
</dt>
1715+
<dd>
1716+
Perform truncate division between two numbers considering bints.
1717+
Truncate division is a division that rounds the quotient towards zero.
1718+
1719+
1720+
<h3>Parameters:</h3>
1721+
<ul>
1722+
<li><span class="parameter">x</span>
1723+
The numerator, a bint or lua number.
1724+
</li>
1725+
<li><span class="parameter">y</span>
1726+
The denominator, a bint or lua number.
1727+
</li>
1728+
</ul>
1729+
1730+
<h3>Returns:</h3>
1731+
<ol>
1732+
1733+
The quotient, a bint or lua number.
1734+
</ol>
1735+
1736+
<h3>Raises:</h3>
1737+
Asserts on attempt to divide by zero or on division overflow.
1738+
1739+
1740+
1741+
</dd>
1742+
<dt>
1743+
<a name = "tmod"></a>
1744+
<strong>tmod (x, y)</strong>
1745+
</dt>
1746+
<dd>
1747+
Perform integer truncate modulo operation between two numbers considering bints.
1748+
The operation is defined as the remainder of the truncate division
1749+
(division that rounds the quotient towards zero).
1750+
1751+
1752+
<h3>Parameters:</h3>
1753+
<ul>
1754+
<li><span class="parameter">x</span>
1755+
The numerator, a bint or lua number.
1756+
</li>
1757+
<li><span class="parameter">y</span>
1758+
The denominator, a bint or lua number.
1759+
</li>
1760+
</ul>
1761+
1762+
<h3>Returns:</h3>
1763+
<ol>
1764+
1765+
The remainder, a bint or lua number.
1766+
</ol>
1767+
1768+
<h3>Raises:</h3>
1769+
Asserts on attempt to divide by zero or on division overflow.
1770+
1771+
1772+
16641773
</dd>
16651774
<dt>
16661775
<a name = "idivmod"></a>
@@ -2370,7 +2479,7 @@ <h2 class="section-header "><a name="Fields"></a>Fields</h2>
23702479
</div> <!-- id="main" -->
23712480
<div id="about">
23722481
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
2373-
<i style="float:right;">Last updated 2020-07-17 10:18:54 </i>
2482+
<i style="float:right;">Last updated 2020-09-24 08:14:54 </i>
23742483
</div> <!-- id="about" -->
23752484
</div> <!-- id="container" -->
23762485
</body>

tests.lua

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ local function test(bits, wordbits)
1010
local bint = require 'bint'(bits, wordbits)
1111
local luabits = luainteger_bitsize()
1212

13-
local function assert_eq(a , b)
13+
local function assert_eq(a, b)
1414
if a ~= b then --luacov:disable
1515
local msg = string.format(
1616
"assertion failed:\n expected '%s' of type '%s',\n but got '%s' of type '%s'",
@@ -19,6 +19,10 @@ local function test(bits, wordbits)
1919
end --luacov:enable
2020
end
2121

22+
local function assert_eqf(a, b)
23+
assert(bint.abs(a - b) <= 1e-6, 'assertion failed')
24+
end
25+
2226
do --utils
2327
assert(bint(-2):iszero() == false)
2428
assert(bint(-1):iszero() == false)
@@ -623,6 +627,31 @@ local function test(bits, wordbits)
623627
test_ops(0xc19076, 0x31ffd4)
624628
end
625629

630+
do --tdivmod
631+
assert_eq(bint.tdiv( 7, 3 ):tointeger(), 2)
632+
assert_eq(bint.tdiv(-7, 3 ):tointeger(), -2)
633+
assert_eq(bint.tdiv( 7, -3 ):tointeger(), -2)
634+
assert_eq(bint.tdiv(-7, -3 ):tointeger(), 2)
635+
assert_eq(bint.tdiv( 6, 3 ):tointeger(), 2)
636+
assert_eq(bint.tdiv(-6, 3 ):tointeger(), -2)
637+
assert_eq(bint.tdiv( 6, -3 ):tointeger(), -2)
638+
assert_eq(bint.tdiv(-6, -3 ):tointeger(), 2)
639+
640+
assert_eq(bint.tmod( 7, 3 ):tointeger(), 1)
641+
assert_eq(bint.tmod(-7, 3 ):tointeger(), -1)
642+
assert_eq(bint.tmod( 7, -3 ):tointeger(), 1)
643+
assert_eq(bint.tmod(-7, -3 ):tointeger(), -1)
644+
assert_eq(bint.tmod( 6, 3 ):tointeger(), 0)
645+
assert_eq(bint.tmod(-6, 3 ):tointeger(), 0)
646+
assert_eq(bint.tmod( 6, -3 ):tointeger(), 0)
647+
assert_eq(bint.tmod(-6, -3 ):tointeger(), 0)
648+
649+
assert_eqf(bint.tdiv(7.5, 2.2), 3.0) assert_eqf(bint.tmod(7.5, 2.2), 0.9)
650+
assert_eqf(bint.tdiv(-7.5, 2.2), -3.0) assert_eqf(bint.tmod(-7.5, 2.2), -0.9)
651+
assert_eqf(bint.tdiv(7.5, -2.2), -3.0) assert_eqf(bint.tmod(7.5, -2.2), 0.9)
652+
assert_eqf(bint.tdiv(-7.5, -2.2), 3.0) assert_eqf(bint.tmod(-7.5, -2.2), -0.9)
653+
end
654+
626655
do -- upowmod
627656
assert_eq(bint.upowmod(65, 17, 3233):tointeger(), 2790)
628657
assert_eq(bint.upowmod(2790, 413, 3233):tointeger(), 65)

0 commit comments

Comments
 (0)