@@ -59,10 +59,10 @@ Then when you need create a bint, you can use one of the following functions:
59
59
60
60
* @{bint.fromuinteger} (convert from lua integers, but read as unsigned integer)
61
61
* @{bint.frominteger} (convert from lua integers, preserving the sign)
62
- * @{bint.fromnumber} (convert from lua floats, truncating the fractional part)
63
62
* @{bint.frombase} (convert from arbitrary bases, like hexadecimal)
63
+ * @{bint.trunc} (convert from lua numbers, truncating the fractional part)
64
64
* @{bint.new} (convert from anything, asserts on invalid integers)
65
- * @{bint.convert } (convert form anything, returns nil on invalid integers)
65
+ * @{bint.tobint } (convert form anything, returns nil on invalid integers)
66
66
* @{bint.parse} (convert from anything, returns a lua number as fallback)
67
67
* @{bint.zero}
68
68
* @{bint.one}
@@ -153,14 +153,20 @@ end
153
153
-- Convert a value to a lua integer without losing precision.
154
154
local function tointeger (x )
155
155
x = tonumber (x )
156
- if math.type (x ) == ' float' then
156
+ local ty = math.type (x )
157
+ if ty == ' float' then
157
158
local floorx = math.floor (x )
158
159
if floorx ~= x then
159
160
return nil
160
161
end
161
162
x = floorx
163
+ ty = math.type (x )
164
+ end
165
+ if ty == ' integer' then
166
+ return x
167
+ else
168
+ return nil
162
169
end
163
- return x
164
170
end
165
171
166
172
-- Check if the input is a bint.
@@ -219,23 +225,6 @@ function bint.frominteger(x)
219
225
return n
220
226
end
221
227
222
- --- Create a bint from a number.
223
- -- Floats values are truncated, that is, the fractional port is discarded.
224
- -- @param x A value to initialize from convertible to a lua number.
225
- -- @return A new bint or nil in case the input cannot be represented by an integer.
226
- function bint .fromnumber (x )
227
- x = tonumber (x )
228
- if not x then
229
- return nil
230
- end
231
- local ty = math.type (x )
232
- if ty == ' float' then
233
- -- truncate to integer
234
- x = math.modf (x )
235
- end
236
- return bint .frominteger (x )
237
- end
238
-
239
228
local basesteps = {}
240
229
241
230
-- Compute the read/write step for frombase/tobase functions.
@@ -361,11 +350,11 @@ local function bint_assert_tointeger(x)
361
350
return assert (bint .tointeger (x ), ' value has no integer representation' )
362
351
end
363
352
364
- --- Convert a bint to a lua number .
353
+ --- Convert a bint to a lua float in case integer would wrap around or lua integer otherwise .
365
354
-- Different from @{bint.tointeger} the operation does not wraps around integers,
366
- -- but digits precision may be lost in the process of converting to a float.
367
- -- @param x A bint or value to be converted into a number.
368
- -- @return An integer or nil in case the input cannot be represented by a number.
355
+ -- but digits precision are lost in the process of converting to a float.
356
+ -- @param x A bint or value to be converted into a lua number.
357
+ -- @return A lua number or nil in case the input cannot be represented by a number.
369
358
-- @see bint.tointeger
370
359
function bint .tonumber (x )
371
360
if isbint (x ) then
403
392
-- @return A string representing the input.
404
393
-- @raise An assert is thrown in case the base is invalid.
405
394
function bint .tobase (x , base , unsigned )
406
- x = bint .convert (x )
395
+ x = bint .tobint (x )
407
396
if not x then
408
397
-- x is a fractional float or something else
409
398
return nil
475
464
-- @param x A value convertible to a bint (string, number or another bint).
476
465
-- @return A new bint, guaranteed to be a new reference in case needed.
477
466
-- @raise An assert is thrown in case x is not convertible to a bint.
478
- -- @see bint.convert
467
+ -- @see bint.tobint
479
468
-- @see bint.parse
480
469
function bint .new (x )
481
470
if isbint (x ) then
499
488
-- @return A bint or nil in case the conversion failed.
500
489
-- @see bint.new
501
490
-- @see bint.parse
502
- function bint .convert (x , clone )
491
+ function bint .tobint (x , clone )
503
492
if isbint (x ) then
504
493
if not clone then
505
494
return x
@@ -512,7 +501,7 @@ function bint.convert(x, clone)
512
501
end
513
502
514
503
local function bint_assert_convert (x )
515
- return assert (bint .convert (x ), ' value has not integer representation' )
504
+ return assert (bint .tobint (x ), ' value has not integer representation' )
516
505
end
517
506
518
507
--- Convert a value to a bint if possible otherwise to a lua number.
522
511
-- Defaults to false.
523
512
-- @return A bint or a lua number or nil in case the conversion failed.
524
513
-- @see bint.new
525
- -- @see bint.convert
514
+ -- @see bint.tobint
526
515
function bint .parse (x , clone )
527
- local i = bint .convert (x , clone )
516
+ local i = bint .tobint (x , clone )
528
517
if i then
529
518
return i
530
519
else
@@ -586,6 +575,24 @@ function bint.isbint(x)
586
575
return isbint (x )
587
576
end
588
577
578
+ --- Check if the input is a lua integer or a bint.
579
+ -- @param x Any lua value.
580
+ function bint .isinteger (x )
581
+ return isbint (x ) or math.type (x ) == ' integer'
582
+ end
583
+
584
+ --- Check the number type of the input (bint, integer or float).
585
+ -- @param x Any lua value.
586
+ -- Returns "bint" for bints, "integer" fot lua integers,
587
+ -- "float" from lua floats or nil otherwise.
588
+ function bint .type (x )
589
+ if isbint (x ) then
590
+ return ' bint'
591
+ else
592
+ return math.type (x )
593
+ end
594
+ end
595
+
589
596
--- Check if a number is negative considering bints.
590
597
-- Zero is guaranteed to never be negative for bints.
591
598
-- @param x A bint or a lua number.
@@ -646,6 +653,26 @@ function bint.one()
646
653
return x
647
654
end
648
655
656
+ --- Create a new bint with the maximum possible integer value.
657
+ function bint .maxinteger ()
658
+ local x = bint_newempty ()
659
+ for i = 1 ,BIGINT_SIZE - 1 do
660
+ x [i ] = BIGINT_WORDMAX
661
+ end
662
+ x [BIGINT_SIZE ] = BIGINT_WORDMAX ~ BIGINT_WORDMSB
663
+ return x
664
+ end
665
+
666
+ --- Create a new bint with the minimum possible integer value.
667
+ function bint .mininteger ()
668
+ local x = bint_newempty ()
669
+ for i = 1 ,BIGINT_SIZE - 1 do
670
+ x [i ] = 0
671
+ end
672
+ x [BIGINT_SIZE ] = BIGINT_WORDMSB
673
+ return x
674
+ end
675
+
649
676
--- Bitwise left shift a bint in one bit (in-place).
650
677
function bint :_shlone ()
651
678
local wordbitsm1 = BIGINT_WORDBITS - 1
710
737
--- Increment a number by one considering bints.
711
738
-- @param x A bint or a lua number to increment.
712
739
function bint .inc (x )
713
- local ix = bint .convert (x , true )
740
+ local ix = bint .tobint (x , true )
714
741
if ix then
715
742
return ix :_inc ()
716
743
else
734
761
--- Decrement a number by one considering bints.
735
762
-- @param x A bint or a lua number to decrement.
736
763
function bint .dec (x )
737
- local ix = bint .convert (x , true )
764
+ local ix = bint .tobint (x , true )
738
765
if ix then
739
766
return ix :_dec ()
740
767
else
@@ -764,14 +791,81 @@ end
764
791
--- Take absolute of a number considering bints.
765
792
-- @param x A bint or a lua number to take the absolute.
766
793
function bint .abs (x )
767
- local ix = bint .convert (x , true )
794
+ local ix = bint .tobint (x , true )
768
795
if ix then
769
796
return ix :_abs ()
770
797
else
771
798
return math.abs (x )
772
799
end
773
800
end
774
801
802
+ --- Take floor of a number considering bints.
803
+ -- @param x A bint or a lua number to perform the floor.
804
+ function bint .floor (x )
805
+ if isbint (x ) then
806
+ return bint .new (x )
807
+ else
808
+ return bint .new (math.floor (tonumber (x )))
809
+ end
810
+ end
811
+
812
+ --- Take ceil of a number considering bints.
813
+ -- @param x A bint or a lua number to perform the ceil.
814
+ function bint .ceil (x )
815
+ if isbint (x ) then
816
+ return bint .new (x )
817
+ else
818
+ return bint .new (math.ceil (tonumber (x )))
819
+ end
820
+ end
821
+
822
+ --- Truncate a lua number to a bint.
823
+ -- Floats numbers are truncated, that is, the fractional port is discarded.
824
+ -- @param x A value to initialize from convertible to a lua number.
825
+ -- @return A new bint or nil in case the input cannot be represented by an integer.
826
+ function bint .trunc (x )
827
+ if not isbint (x ) then
828
+ x = tonumber (x )
829
+ if not x then
830
+ return nil
831
+ end
832
+ local ty = math.type (x )
833
+ if ty == ' float' then
834
+ -- truncate to integer
835
+ x = math.modf (x )
836
+ end
837
+ return bint .frominteger (x )
838
+ else
839
+ return bint .new (x )
840
+ end
841
+ end
842
+
843
+ --- Take maximum between two numbers considering bints.
844
+ -- @param x A bint or lua number to compare.
845
+ -- @param y A bint or lua number to compare.
846
+ -- @return A bint or a lua number. Guarantees to return a new bint for integer values.
847
+ function bint .max (x , y )
848
+ local ix , iy = bint .tobint (x ), bint .tobint (y )
849
+ if ix and iy then
850
+ return bint .new (ix > iy and ix or iy )
851
+ else
852
+ return bint .parse (math.max (x , y ))
853
+ end
854
+ end
855
+
856
+ --- Take minimum between two numbers considering bints.
857
+ -- @param x A bint or lua number to compare.
858
+ -- @param y A bint or lua number to compare.
859
+ -- @return A bint or a lua number. Guarantees to return a new bint for integer values.
860
+ function bint .min (x , y )
861
+ local ix , iy = bint .tobint (x ), bint .tobint (y )
862
+ if ix and iy then
863
+ return bint .new (ix < iy and ix or iy )
864
+ else
865
+ return bint .parse (math.min (x , y ))
866
+ end
867
+ end
868
+
775
869
--- Add an integer to a bint (in-place).
776
870
-- @param y An integer to be added.
777
871
-- @raise Asserts in case inputs are not convertible to integers.
790
884
-- @param x A bint or a lua number to be added.
791
885
-- @param y A bint or a lua number to be added.
792
886
function bint .__add (x , y )
793
- local ix = bint .convert (x )
794
- local iy = bint .convert (y )
887
+ local ix , iy = bint .tobint (x ), bint .tobint (y )
795
888
if ix and iy then
796
889
local z = bint_newempty ()
797
890
local carry = 0
825
918
-- @param x A bint or a lua number to be subtract from.
826
919
-- @param y A bint or a lua number to subtract.
827
920
function bint .__sub (x , y )
828
- local ix = bint .convert (x )
829
- local iy = bint .convert (y )
921
+ local ix , iy = bint .tobint (x ), bint .tobint (y )
830
922
if ix and iy then
831
923
local z = bint_newempty ()
832
924
local borrow = 0
846
938
-- @param x A bint or a lua number to multiply.
847
939
-- @param y A bint or a lua number to multiply.
848
940
function bint .__mul (x , y )
849
- local ix = bint .convert (x )
850
- local iy = bint .convert (y )
941
+ local ix , iy = bint .tobint (x ), bint .tobint (y )
851
942
if ix and iy then
852
943
local z = bint .zero ()
853
944
local sizep1 = BIGINT_SIZE + 1
982
1073
-- @see bint.__idiv
983
1074
-- @see bint.__mod
984
1075
function bint .idivmod (x , y )
985
- local ix = bint .convert (x )
986
- local iy = bint .convert (y )
1076
+ local ix , iy = bint .tobint (x ), bint .tobint (y )
987
1077
if ix and iy then
988
1078
if iy :isminusone () then
989
1079
return - ix , bint .zero ()
@@ -1265,7 +1355,7 @@ end
1265
1355
-- @param x A bint or lua number to compare.
1266
1356
-- @param y A bint or lua number to compare.
1267
1357
function bint .eq (x , y )
1268
- return bint .convert (x ) == bint .convert (y )
1358
+ return bint .tobint (x ) == bint .tobint (y )
1269
1359
end
1270
1360
1271
1361
--- Compare if integer x is less than y considering bints (unsigned version).
@@ -1305,7 +1395,7 @@ end
1305
1395
-- @param y Right value to compare, a bint or lua number.
1306
1396
-- @see bint.ult
1307
1397
function bint .__lt (x , y )
1308
- local ix , iy = bint .convert (x ), bint .convert (y )
1398
+ local ix , iy = bint .tobint (x ), bint .tobint (y )
1309
1399
if ix and iy then
1310
1400
local xneg = ix [BIGINT_SIZE ] & BIGINT_WORDMSB ~= 0
1311
1401
local yneg = iy [BIGINT_SIZE ] & BIGINT_WORDMSB ~= 0
@@ -1330,7 +1420,7 @@ end
1330
1420
-- @param y Right value to compare, a bint or lua number.
1331
1421
-- @see bint.ule
1332
1422
function bint .__le (x , y )
1333
- local ix , iy = bint .convert (x ), bint .convert (y )
1423
+ local ix , iy = bint .tobint (x ), bint .tobint (y )
1334
1424
if ix and iy then
1335
1425
local xneg = ix [BIGINT_SIZE ] & BIGINT_WORDMSB ~= 0
1336
1426
local yneg = iy [BIGINT_SIZE ] & BIGINT_WORDMSB ~= 0
0 commit comments