394
394
end
395
395
end
396
396
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
-
411
397
--- Convert a bint to a string in the desired base.
412
398
-- @param x The bint to be converted from.
413
399
-- @param [opt] base Base to be represented, defaults to 10.
@@ -446,9 +432,11 @@ function bint.tobase(x, base, unsigned)
446
432
local neg = not unsigned and x :isneg ()
447
433
if neg then
448
434
x = x :abs ()
435
+ else
436
+ x = bint .new (x )
449
437
end
450
- local stop = x :iszero ()
451
- if stop then
438
+ local xiszero = x :iszero ()
439
+ if xiszero then
452
440
return ' 0'
453
441
end
454
442
-- calculate basepow
@@ -459,21 +447,33 @@ function bint.tobase(x, base, unsigned)
459
447
step = step + 1
460
448
basepow = basepow * base
461
449
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
467
468
for _ = 1 ,step do
468
- local d
469
469
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
471
471
-- stop on leading zeros
472
472
break
473
473
end
474
474
table.insert (ss , 1 , BASE_LETTERS [d ])
475
475
end
476
- end
476
+ until xiszero
477
477
if neg then
478
478
table.insert (ss , 1 , ' -' )
479
479
end
@@ -1063,6 +1063,19 @@ local function findleftbit(x)
1063
1063
end
1064
1064
end
1065
1065
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
+
1066
1079
--- Perform unsigned division and modulo operation between two integers considering bints.
1067
1080
-- This is effectively the same of @{bint.udiv} and @{bint.umod}.
1068
1081
-- @param x The numerator, must be a bint or a lua integer.
@@ -1077,7 +1090,7 @@ function bint.udivmod(x, y)
1077
1090
local deno = bint_assert_convert (y )
1078
1091
-- compute if high bits of denominator are all zeros
1079
1092
local ishighzero = true
1080
- for i = BINT_SIZE , 2 , - 1 do
1093
+ for i = 2 , BINT_SIZE do
1081
1094
if deno [i ] ~= 0 then
1082
1095
ishighzero = false
1083
1096
break
@@ -1092,9 +1105,8 @@ function bint.udivmod(x, y)
1092
1105
return nume , bint .zero ()
1093
1106
elseif low <= (BINT_WORDMSB - 1 ) then
1094
1107
-- 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 )
1098
1110
end
1099
1111
end
1100
1112
if nume :ult (deno ) then
@@ -1188,9 +1200,6 @@ end
1188
1200
function bint .idivmod (x , y )
1189
1201
local ix , iy = bint .tobint (x ), bint .tobint (y )
1190
1202
if ix and iy then
1191
- if iy :isminusone () then
1192
- return - ix , bint .zero ()
1193
- end
1194
1203
local quot , rema = bint .udivmod (ix :abs (), iy :abs ())
1195
1204
local isnumneg , isdenomneg = ix :isneg (), iy :isneg ()
1196
1205
if isnumneg ~= isdenomneg then
@@ -1226,9 +1235,6 @@ end
1226
1235
function bint .__idiv (x , y )
1227
1236
local ix , iy = bint .tobint (x ), bint .tobint (y )
1228
1237
if ix and iy then
1229
- if iy :isminusone () then
1230
- return - ix , bint .zero ()
1231
- end
1232
1238
local quot , rema = bint .udivmod (ix :abs (), iy :abs ())
1233
1239
if ix :isneg () ~= iy :isneg () then
1234
1240
quot :_unm ()
0 commit comments