Browse Source

Add working `ToInt()` method

pull/8/head
Anton Tarasenko 2 years ago
parent
commit
97f776c6bc
  1. 65
      sources/BaseRealm/API/Math/BigInt.uc
  2. 33
      sources/BaseRealm/API/Math/Tests/TEST_BigInt.uc

65
sources/BaseRealm/API/Math/BigInt.uc

@ -41,8 +41,9 @@ var private bool negative;
// Valid `BigInt` should not have this array empty. // Valid `BigInt` should not have this array empty.
var private array<byte> digits; var private array<byte> digits;
private const ALMOST_MAX_INT = 147483647; const ALMOST_MAX_INT = 147483647;
private const DIGITS_IN_MAX_INT = 10; const DIGITS_IN_MAX_INT = 10;
const LAST_DIGIT_ORDER = 1000000000;
protected function Constructor() protected function Constructor()
{ {
@ -365,12 +366,12 @@ public function int ToInt()
{ {
local int i; local int i;
local int accumulator; local int accumulator;
local int mostSignificantDigit; local int safeDigitsAmount;
if (digits.lenght <= 0) { if (digits.length <= 0) {
return 0; return 0;
} }
if (digits.lenght > DIGITS_IN_MAX_INT) if (digits.length > DIGITS_IN_MAX_INT)
{ {
if (negative) { if (negative) {
return (-MaxInt - 1); return (-MaxInt - 1);
@ -379,21 +380,57 @@ public function int ToInt()
return MaxInt; return MaxInt;
} }
} }
mostSignificantDigit = -1;
if (digits.lenght == DIGITS_IN_MAX_INT)
{
mostSignificantDigit = digits[digits.length - 1];
digits[i] = DIGITS_IN_MAX_INT - 1;
}
// At most `DIGITS_IN_MAX_INT - 1` iterations // At most `DIGITS_IN_MAX_INT - 1` iterations
for (i = 0; i < digits.length; i += 1) safeDigitsAmount = Min(DIGITS_IN_MAX_INT - 1, digits.length);
{//ALMOST_MAX_INT for (i = safeDigitsAmount - 1; i >= 0; i -= 1)
{
accumulator *= 10; accumulator *= 10;
accumulator += digits[i]; accumulator += digits[i];
} }
if (mostSignificantDigit < 0) { if (negative) {
accumulator *= -1;
}
accumulator = AddUnsafeDigitToInt(accumulator);
return accumulator;
}
// Assumes `digits.length <= DIGITS_IN_MAX_INT`
private function int AddUnsafeDigitToInt(int accumulator)
{
local int unsafeDigit;
local bool noOverflow;
if (digits.length < DIGITS_IN_MAX_INT) {
return accumulator;
}
unsafeDigit = digits[DIGITS_IN_MAX_INT - 1];
// `MaxInt` stats with `2`, so if last/unsafe digit is either `0` or `1`,
// there is no overflow, otherwise - check rest of the digits
noOverflow = (unsafeDigit < 2);
if (unsafeDigit == 2)
{
// Include `MaxInt` and `-MaxInt-1` (minimal possible value) into
// an overflow too - this way we still give a correct result, but do
// not have to worry about `int`-arithmetic error
noOverflow = noOverflow
|| (negative && (accumulator > -ALMOST_MAX_INT - 1))
|| (!negative && (accumulator < ALMOST_MAX_INT));
}
if (noOverflow)
{
if (negative) {
accumulator -= unsafeDigit * LAST_DIGIT_ORDER;
}
else {
accumulator += unsafeDigit * LAST_DIGIT_ORDER;
}
return accumulator; return accumulator;
} }
// Handle overflow
if (negative) {
return (-MaxInt - 1);
}
return MaxInt;
} }
public function Text ToText() public function Text ToText()

33
sources/BaseRealm/API/Math/Tests/TEST_BigInt.uc

@ -24,9 +24,13 @@ protected static function TESTS()
{ {
// Here we use `ToString()` method to check `BigInt` creation, // Here we use `ToString()` method to check `BigInt` creation,
// therefore also testing it // therefore also testing it
Context("Testing creation of `BigInt`s.");
Test_Creating(); Test_Creating();
// So here we nee to test `ToText()` methods separately // So here we nee to test `ToText()` methods separately
Context("Testing `ToText()` method of `BigInt`s.");
Test_ToText(); Test_ToText();
Context("Testing `ToInt()` method of `BigInt`s.");
Test_ToInt();
Context("Testing basic arithmetic operations on `BigInt`s."); Context("Testing basic arithmetic operations on `BigInt`s.");
Test_AddingValues(); Test_AddingValues();
Test_SubtractingValues(); Test_SubtractingValues();
@ -34,7 +38,6 @@ protected static function TESTS()
protected static function Test_Creating() protected static function Test_Creating()
{ {
Context("Testing creation of `BigInt`s.");
Issue("`ToString()` doesn't return value `BigInt` was initialized with" @ Issue("`ToString()` doesn't return value `BigInt` was initialized with" @
"a positive `int`."); "a positive `int`.");
TEST_ExpectTrue(__().math.ToBigInt(13524).ToString() == "13524"); TEST_ExpectTrue(__().math.ToBigInt(13524).ToString() == "13524");
@ -70,7 +73,6 @@ protected static function Test_Creating()
protected static function Test_ToText() protected static function Test_ToText()
{ {
Context("Testing `ToText()` method of `BigInt`s.");
Issue("`ToText()` doesn't return value `BigInt` was initialized with" @ Issue("`ToText()` doesn't return value `BigInt` was initialized with" @
"a positive integer inside `string`."); "a positive integer inside `string`.");
TEST_ExpectTrue(__().math TEST_ExpectTrue(__().math
@ -204,7 +206,7 @@ protected static function SubTest_SubtractingSameSignValues()
main.Subtract(sub); main.Subtract(sub);
TEST_ExpectTrue(main.ToString() == "0"); TEST_ExpectTrue(main.ToString() == "0");
} }
//Negative `BigInt`s is incorrectly subtracted from positive one. [2]
protected static function SubTest_SubtractingDifferentSignValues() protected static function SubTest_SubtractingDifferentSignValues()
{ {
local BigInt main, sub; local BigInt main, sub;
@ -236,7 +238,30 @@ protected static function SubTest_SubtractingDifferentSignValues()
sub = __().math.MakeBigInt_S("728965872936589276"); sub = __().math.MakeBigInt_S("728965872936589276");
main.Subtract(sub); main.Subtract(sub);
TEST_ExpectTrue(main.ToString() == "-1457931745873178552"); TEST_ExpectTrue(main.ToString() == "-1457931745873178552");
Log("UMBRA TEST"); }
protected static function Test_ToInt()
{
Issue("Testing conversion for non-overflowing values.");
TEST_ExpectTrue(__().math.MakeBigInt_S("0").ToInt() == 0);
TEST_ExpectTrue(__().math.MakeBigInt_S("-0").ToInt() == 0);
TEST_ExpectTrue(__().math.MakeBigInt_S("13524").ToInt() == 13524);
TEST_ExpectTrue(__().math.MakeBigInt_S("-666").ToInt() == -666);
TEST_ExpectTrue(__().math.MakeBigInt_S("2147483647").ToInt() == 2147483647);
TEST_ExpectTrue(__().math.MakeBigInt_S("2147483646").ToInt() == 2147483646);
TEST_ExpectTrue(
__().math.MakeBigInt_S("-2147483648").ToInt() == -2147483648);
TEST_ExpectTrue(
__().math.MakeBigInt_S("-2147483647").ToInt() == -2147483647);
Issue("Testing conversion for overflowing values.");
TEST_ExpectTrue(__().math.MakeBigInt_S("2147483648").ToInt() == 2147483647);
TEST_ExpectTrue(
__().math.MakeBigInt_S("8342748293074932473246").ToInt() == 2147483647);
TEST_ExpectTrue(
__().math.MakeBigInt_S("-2147483649").ToInt() == -2147483648);
TEST_ExpectTrue(
__().math.MakeBigInt_S("-32545657348437563873").ToInt() == -2147483648);
} }
defaultproperties defaultproperties

Loading…
Cancel
Save