@@ -1065,19 +1065,23 @@ function bint.udivmod(x, y)
1065
1065
local divisor = bint_assert_convert (y )
1066
1066
local quot = bint .zero ()
1067
1067
assert (not divisor :iszero (), ' attempt to divide by zero' )
1068
- if dividend :ult (divisor ) then
1068
+ if divisor :isone () then
1069
+ return dividend , bint .zero ()
1070
+ elseif dividend :ult (divisor ) then
1069
1071
return quot , dividend
1070
1072
end
1071
1073
-- align leftmost digits in dividend and divisor
1072
1074
local divisorlbit = findleftbit (divisor )
1073
- local divdendlbit , size = findleftbit (dividend )
1075
+ local divdendlbit , divdendsize = findleftbit (dividend )
1074
1076
local bit = divdendlbit - divisorlbit
1075
1077
divisor = divisor << bit
1076
1078
local wordmaxp1 = BINT_WORDMAX + 1
1077
1079
local wordbitsm1 = BINT_WORDBITS - 1
1080
+ local divisorsize = divdendsize
1078
1081
while bit >= 0 do
1079
1082
-- compute divisor <= dividend
1080
1083
local le = true
1084
+ local size = math.max (divdendsize , divisorsize )
1081
1085
for i = size ,1 ,- 1 do
1082
1086
local a , b = divisor [i ], dividend [i ]
1083
1087
if a ~= b then
@@ -1099,10 +1103,20 @@ function bint.udivmod(x, y)
1099
1103
quot [i ] = quot [i ] | (1 << (bit % BINT_WORDBITS ))
1100
1104
end
1101
1105
-- shift right the divisor in one bit
1102
- for i = 1 ,size - 1 do
1106
+ for i = 1 ,divisorsize - 1 do
1103
1107
divisor [i ] = ((divisor [i ] >> 1 ) | (divisor [i + 1 ] << wordbitsm1 )) & BINT_WORDMAX
1104
1108
end
1105
- divisor [size ] = divisor [size ] >> 1
1109
+ local lastdivisorword = divisor [divisorsize ] >> 1
1110
+ divisor [divisorsize ] = lastdivisorword
1111
+ -- recalculate divisor size (optimization)
1112
+ if lastdivisorword == 0 then
1113
+ while divisor [divisorsize ] == 0 do
1114
+ divisorsize = divisorsize - 1
1115
+ end
1116
+ if divisorsize == 0 then
1117
+ break
1118
+ end
1119
+ end
1106
1120
-- decrement current set bit for the quotient
1107
1121
bit = bit - 1
1108
1122
end
0 commit comments