245
245
246
246
local basesteps = {}
247
247
248
- -- Compute the read/write step for frombase/tobase functions.
248
+ -- Compute the read step for frombase function
249
249
local function getbasestep (base )
250
250
local step = basesteps [base ]
251
251
if step then
394
394
end
395
395
end
396
396
397
- -- Get the quotient and remainder for a lua integer division
398
- local function idivmod (x , y )
399
- local quot = x // y
400
- local rem = x - (quot * y )
401
- return quot , rem
397
+ -- Get the quotient and remainder for base digits
398
+ local function xremainder (dividend , divisor )
399
+ local quo = bint_newempty ()
400
+ local rem
401
+ local carry = 0
402
+ for i = BINT_SIZE ,1 ,- 1 do
403
+ carry = carry | dividend [i ]
404
+ quo [i ] = carry // divisor
405
+ rem = carry % divisor
406
+ carry = rem << BINT_WORDBITS
407
+ end
408
+ return quo , rem
402
409
end
403
410
404
411
--- Convert a bint to a string in the desired base.
@@ -441,26 +448,13 @@ function bint.tobase(x, base, unsigned)
441
448
if neg then
442
449
x = x :abs ()
443
450
end
444
- local step = getbasestep (base )
445
- local divisor = bint .new (ipow (1 , base , step ))
446
- local stop = x :iszero ()
447
- if stop then
448
- return ' 0'
451
+ while not x :iszero () do
452
+ local d
453
+ x , d = xremainder (x , base )
454
+ table.insert (ss , 1 , BASE_LETTERS [d ])
449
455
end
450
- while not stop do
451
- local ix
452
- x , ix = bint .udivmod (x , divisor )
453
- ix = ix :tointeger ()
454
- stop = x :iszero ()
455
- for _ = 1 ,step do
456
- local d
457
- ix , d = idivmod (ix , base )
458
- if stop and ix == 0 and d == 0 then
459
- -- stop on leading zeros
460
- break
461
- end
462
- table.insert (ss , 1 , BASE_LETTERS [d ])
463
- end
456
+ if # ss == 0 then
457
+ return ' 0'
464
458
end
465
459
if neg then
466
460
table.insert (ss , 1 , ' -' )
@@ -1063,12 +1057,12 @@ end
1063
1057
function bint .udivmod (x , y )
1064
1058
local dividend = bint .new (x )
1065
1059
local divisor = bint_assert_convert (y )
1066
- local quot = bint .zero ()
1060
+ local quo = bint .zero ()
1067
1061
assert (not divisor :iszero (), ' attempt to divide by zero' )
1068
1062
if divisor :isone () then
1069
1063
return dividend , bint .zero ()
1070
1064
elseif dividend :ult (divisor ) then
1071
- return quot , dividend
1065
+ return quo , dividend
1072
1066
end
1073
1067
-- align leftmost digits in dividend and divisor
1074
1068
local divisorlbit = findleftbit (divisor )
@@ -1100,7 +1094,7 @@ function bint.udivmod(x, y)
1100
1094
end
1101
1095
-- concatenate 1 to the right bit of the quotient
1102
1096
local i = (bit // BINT_WORDBITS ) + 1
1103
- quot [i ] = quot [i ] | (1 << (bit % BINT_WORDBITS ))
1097
+ quo [i ] = quo [i ] | (1 << (bit % BINT_WORDBITS ))
1104
1098
end
1105
1099
-- shift right the divisor in one bit
1106
1100
for i = 1 ,divisorsize - 1 do
@@ -1121,7 +1115,7 @@ function bint.udivmod(x, y)
1121
1115
bit = bit - 1
1122
1116
end
1123
1117
-- the remaining dividend is the remainder
1124
- return quot , dividend
1118
+ return quo , dividend
1125
1119
end
1126
1120
1127
1121
--- Perform unsigned division between two integers considering bints.
@@ -1159,13 +1153,13 @@ function bint.idivmod(x, y)
1159
1153
if iy :isminusone () then
1160
1154
return - ix , bint .zero ()
1161
1155
end
1162
- local quot , rem = bint .udivmod (ix :abs (), iy :abs ())
1156
+ local quo , rem = bint .udivmod (ix :abs (), iy :abs ())
1163
1157
local isnumneg , isdenomneg = ix :isneg (), iy :isneg ()
1164
1158
if isnumneg ~= isdenomneg then
1165
- quot :_unm ()
1159
+ quo :_unm ()
1166
1160
-- round quotient towards minus infinity
1167
1161
if not rem :iszero () then
1168
- quot :_dec ()
1162
+ quo :_dec ()
1169
1163
-- adjust the remainder
1170
1164
if isnumneg and not isdenomneg then
1171
1165
rem :_unm ():_add (y )
@@ -1177,9 +1171,10 @@ function bint.idivmod(x, y)
1177
1171
-- adjust the remainder
1178
1172
rem :_unm ()
1179
1173
end
1180
- return quot , rem
1174
+ return quo , rem
1181
1175
else
1182
- return idivmod (bint .tonumber (x ), bint .tonumber (y ))
1176
+ local nx , ny = bint .tonumber (x ), bint .tonumber (y )
1177
+ return nx // ny , nx % ny
1183
1178
end
1184
1179
end
1185
1180
0 commit comments