245245
246246local basesteps = {}
247247
248- -- Compute the read/write step for frombase/tobase functions.
248+ -- Compute the read step for frombase function
249249local function getbasestep (base )
250250 local step = basesteps [base ]
251251 if step then
394394 end
395395end
396396
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
402409end
403410
404411--- Convert a bint to a string in the desired base.
@@ -441,26 +448,13 @@ function bint.tobase(x, base, unsigned)
441448 if neg then
442449 x = x :abs ()
443450 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 ])
449455 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'
464458 end
465459 if neg then
466460 table.insert (ss , 1 , ' -' )
@@ -1063,12 +1057,12 @@ end
10631057function bint .udivmod (x , y )
10641058 local dividend = bint .new (x )
10651059 local divisor = bint_assert_convert (y )
1066- local quot = bint .zero ()
1060+ local quo = bint .zero ()
10671061 assert (not divisor :iszero (), ' attempt to divide by zero' )
10681062 if divisor :isone () then
10691063 return dividend , bint .zero ()
10701064 elseif dividend :ult (divisor ) then
1071- return quot , dividend
1065+ return quo , dividend
10721066 end
10731067 -- align leftmost digits in dividend and divisor
10741068 local divisorlbit = findleftbit (divisor )
@@ -1100,7 +1094,7 @@ function bint.udivmod(x, y)
11001094 end
11011095 -- concatenate 1 to the right bit of the quotient
11021096 local i = (bit // BINT_WORDBITS ) + 1
1103- quot [i ] = quot [i ] | (1 << (bit % BINT_WORDBITS ))
1097+ quo [i ] = quo [i ] | (1 << (bit % BINT_WORDBITS ))
11041098 end
11051099 -- shift right the divisor in one bit
11061100 for i = 1 ,divisorsize - 1 do
@@ -1121,7 +1115,7 @@ function bint.udivmod(x, y)
11211115 bit = bit - 1
11221116 end
11231117 -- the remaining dividend is the remainder
1124- return quot , dividend
1118+ return quo , dividend
11251119end
11261120
11271121--- Perform unsigned division between two integers considering bints.
@@ -1159,13 +1153,13 @@ function bint.idivmod(x, y)
11591153 if iy :isminusone () then
11601154 return - ix , bint .zero ()
11611155 end
1162- local quot , rem = bint .udivmod (ix :abs (), iy :abs ())
1156+ local quo , rem = bint .udivmod (ix :abs (), iy :abs ())
11631157 local isnumneg , isdenomneg = ix :isneg (), iy :isneg ()
11641158 if isnumneg ~= isdenomneg then
1165- quot :_unm ()
1159+ quo :_unm ()
11661160 -- round quotient towards minus infinity
11671161 if not rem :iszero () then
1168- quot :_dec ()
1162+ quo :_dec ()
11691163 -- adjust the remainder
11701164 if isnumneg and not isdenomneg then
11711165 rem :_unm ():_add (y )
@@ -1177,9 +1171,10 @@ function bint.idivmod(x, y)
11771171 -- adjust the remainder
11781172 rem :_unm ()
11791173 end
1180- return quot , rem
1174+ return quo , rem
11811175 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
11831178 end
11841179end
11851180
0 commit comments