394394 end
395395end
396396
397- -- Single word division modulus
398- local function sudivmod (nume , deno )
399- local quot = bint_newempty ()
400- local rema
401- local carry = 0
402- for i = BINT_SIZE ,1 ,- 1 do
403- carry = carry | nume [i ]
404- quot [i ] = carry // deno
405- rema = carry % deno
406- carry = rema << BINT_WORDBITS
407- end
408- return quot , rema
409- end
410-
411397--- Convert a bint to a string in the desired base.
412398-- @param x The bint to be converted from.
413399-- @param [opt] base Base to be represented, defaults to 10.
@@ -446,9 +432,11 @@ function bint.tobase(x, base, unsigned)
446432 local neg = not unsigned and x :isneg ()
447433 if neg then
448434 x = x :abs ()
435+ else
436+ x = bint .new (x )
449437 end
450- local stop = x :iszero ()
451- if stop then
438+ local xiszero = x :iszero ()
439+ if xiszero then
452440 return ' 0'
453441 end
454442 -- calculate basepow
@@ -459,21 +447,33 @@ function bint.tobase(x, base, unsigned)
459447 step = step + 1
460448 basepow = basepow * base
461449 until basepow >= limit
462- -- spit out base digits
463- while not stop do
464- local xd
465- x , xd = sudivmod (x , basepow )
466- stop = x :iszero ()
450+ -- serialize base digits
451+ local size = BINT_SIZE
452+ local xd , carry , d
453+ repeat
454+ -- single word division
455+ carry = 0
456+ xiszero = true
457+ for i = size ,1 ,- 1 do
458+ carry = carry | x [i ]
459+ d , xd = carry // basepow , carry % basepow
460+ if xiszero and d ~= 0 then
461+ size = i
462+ xiszero = false
463+ end
464+ x [i ] = d
465+ carry = xd << BINT_WORDBITS
466+ end
467+ -- digit division
467468 for _ = 1 ,step do
468- local d
469469 xd , d = xd // base , xd % base
470- if stop and xd == 0 and d == 0 then
470+ if xiszero and xd == 0 and d == 0 then
471471 -- stop on leading zeros
472472 break
473473 end
474474 table.insert (ss , 1 , BASE_LETTERS [d ])
475475 end
476- end
476+ until xiszero
477477 if neg then
478478 table.insert (ss , 1 , ' -' )
479479 end
@@ -1063,6 +1063,19 @@ local function findleftbit(x)
10631063 end
10641064end
10651065
1066+ -- Single word division modulus
1067+ local function sudivmod (nume , deno )
1068+ local rema
1069+ local carry = 0
1070+ for i = BINT_SIZE ,1 ,- 1 do
1071+ carry = carry | nume [i ]
1072+ nume [i ] = carry // deno
1073+ rema = carry % deno
1074+ carry = rema << BINT_WORDBITS
1075+ end
1076+ return rema
1077+ end
1078+
10661079--- Perform unsigned division and modulo operation between two integers considering bints.
10671080-- This is effectively the same of @{bint.udiv} and @{bint.umod}.
10681081-- @param x The numerator, must be a bint or a lua integer.
@@ -1077,7 +1090,7 @@ function bint.udivmod(x, y)
10771090 local deno = bint_assert_convert (y )
10781091 -- compute if high bits of denominator are all zeros
10791092 local ishighzero = true
1080- for i = BINT_SIZE , 2 , - 1 do
1093+ for i = 2 , BINT_SIZE do
10811094 if deno [i ] ~= 0 then
10821095 ishighzero = false
10831096 break
@@ -1092,9 +1105,8 @@ function bint.udivmod(x, y)
10921105 return nume , bint .zero ()
10931106 elseif low <= (BINT_WORDMSB - 1 ) then
10941107 -- can do single word division
1095- local rema
1096- nume , rema = sudivmod (nume , low )
1097- return nume , bint .new (rema )
1108+ local rema = sudivmod (nume , low )
1109+ return nume , bint .fromuinteger (rema )
10981110 end
10991111 end
11001112 if nume :ult (deno ) then
@@ -1188,9 +1200,6 @@ end
11881200function bint .idivmod (x , y )
11891201 local ix , iy = bint .tobint (x ), bint .tobint (y )
11901202 if ix and iy then
1191- if iy :isminusone () then
1192- return - ix , bint .zero ()
1193- end
11941203 local quot , rema = bint .udivmod (ix :abs (), iy :abs ())
11951204 local isnumneg , isdenomneg = ix :isneg (), iy :isneg ()
11961205 if isnumneg ~= isdenomneg then
@@ -1226,9 +1235,6 @@ end
12261235function bint .__idiv (x , y )
12271236 local ix , iy = bint .tobint (x ), bint .tobint (y )
12281237 if ix and iy then
1229- if iy :isminusone () then
1230- return - ix , bint .zero ()
1231- end
12321238 local quot , rema = bint .udivmod (ix :abs (), iy :abs ())
12331239 if ix :isneg () ~= iy :isneg () then
12341240 quot :_unm ()
0 commit comments