654 lines
21 KiB
Ucode
654 lines
21 KiB
Ucode
/**
|
|
* Author: dkanus
|
|
* Home repo: https://www.insultplayers.ru/git/AcediaFramework/AcediaCore
|
|
* License: GPL
|
|
* Copyright 2022-2023 Anton Tarasenko
|
|
*------------------------------------------------------------------------------
|
|
* This file is part of Acedia.
|
|
*
|
|
* Acedia is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Acedia is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Acedia. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
class BigInt extends AcediaObject
|
|
dependson(MathApi);
|
|
|
|
/// A simple big integer implementation.
|
|
///
|
|
/// [`BigInt`]'s main purpose is to allow Acedia's databases to store integers of arbitrary size.
|
|
/// It can be used for long arithmetic computations, but it was mainly meant as a players'
|
|
/// statistics counter and, therefore, not optimized for performing large amount of operations.
|
|
|
|
/// [`BigInt`] data as a struct - meant to be used to store [`BigInt`]'s values inside
|
|
/// the local databases.
|
|
struct BigIntData {
|
|
var bool negative;
|
|
var array<byte> digits;
|
|
};
|
|
|
|
/// Result of comparison for [`BigInt`]s with each other.
|
|
enum BigIntCompareResult
|
|
{
|
|
BICR_Less,
|
|
BICR_Equal,
|
|
BICR_Greater
|
|
};
|
|
|
|
/// Does stored [`BigInt`] have a negative sign?
|
|
var private bool negative;
|
|
/// Digits array, from least to most significant. For example, for 13524:
|
|
///
|
|
/// ```
|
|
/// `digits[0] = 4`
|
|
/// `digits[1] = 2`
|
|
/// `digits[2] = 5`
|
|
/// `digits[3] = 3`
|
|
/// `digits[4] = 1`
|
|
/// ```
|
|
///
|
|
/// Valid [`BigInt`] should not have this array empty: zero should be represented by an array with
|
|
/// a single `0`-element.
|
|
/// This isn't a most efficient representation for [`BigInt`], but it's easy to convert to and from
|
|
/// decimal representation.
|
|
///
|
|
/// # Invariants
|
|
///
|
|
/// This array must not have leading (in the sense of significance) zeroes.
|
|
/// That is, last element of the array should not be a `0`.
|
|
/// The only exception if if stored value is `0`, then `digits` must consist of
|
|
/// a single `0` element.
|
|
var private array<byte> digits;
|
|
|
|
/// Constants useful for converting [`BigInt`] back to [`int`], while avoiding overflow.
|
|
/// We can add less digits than that without any fear of overflow.
|
|
const DIGITS_IN_MAX_INT = 10;
|
|
/// Maximum [`int`] value is `2147483647`, so in case most significant digit is 10th and is `2`
|
|
/// (so number has a form of `2xxxxxxxxx`), to check for overflow we only need to compare
|
|
/// combination of the rest of the digits with this constant.
|
|
const ALMOST_MAX_INT = 147483647;
|
|
/// To add last digit we add/subtract that digit multiplied by this value.
|
|
const LAST_DIGIT_ORDER = 1000000000;
|
|
|
|
protected function Constructor() {
|
|
SetZero();
|
|
}
|
|
|
|
protected function Finalizer() {
|
|
negative = false;
|
|
digits.length = 0;
|
|
}
|
|
|
|
// Auxiliary method to set current value to zero
|
|
private function SetZero() {
|
|
negative = false;
|
|
digits.length = 1;
|
|
digits[0] = 0;
|
|
}
|
|
|
|
// Minimal [`int`] value `-2,147,483,648` is somewhat of a pain to handle, so just use this
|
|
// auxiliary pre-made constructor for it
|
|
private function SetMinimalNegative() {
|
|
negative = true;
|
|
digits.length = 10;
|
|
digits[0] = 8;
|
|
digits[1] = 4;
|
|
digits[2] = 6;
|
|
digits[3] = 3;
|
|
digits[4] = 8;
|
|
digits[5] = 4;
|
|
digits[6] = 7;
|
|
digits[7] = 4;
|
|
digits[8] = 1;
|
|
digits[9] = 2;
|
|
}
|
|
|
|
// Removes unnecessary zeroes from leading digit positions `digits`.
|
|
// Does not change contained value.
|
|
private final function TrimLeadingZeroes() {
|
|
local int i, zeroesToRemove;
|
|
|
|
// Finds how many leading zeroes there is.
|
|
// Since `digits` stores digits from least to most significant, we need to check from the end of
|
|
// `digits` array.
|
|
for (i = digits.length - 1; i >= 0; i -= 1) {
|
|
if (digits[i] != 0) {
|
|
break;
|
|
}
|
|
zeroesToRemove += 1;
|
|
}
|
|
// `digits` must not be empty, enforce `0` value in that case
|
|
if (zeroesToRemove >= digits.length) {
|
|
SetZero();
|
|
}
|
|
else {
|
|
digits.length = digits.length - zeroesToRemove;
|
|
}
|
|
}
|
|
|
|
/// Changes current value of [`BigInt`] to given value.
|
|
public final function Set(BigInt value)
|
|
{
|
|
if (value != none) {
|
|
value.TrimLeadingZeroes();
|
|
digits = value.digits;
|
|
negative = value.negative;
|
|
}
|
|
}
|
|
|
|
/// Changes current value of [`BigInt`] to given value.
|
|
public final function SetInt(int value) {
|
|
local MathApi.IntegerDivisionResult divisionResult;
|
|
|
|
negative = false;
|
|
digits.length = 0;
|
|
if (value < 0) {
|
|
// Treat special case of minimal [`int`] value `-2,147,483,648` that
|
|
// won't fit into positive [`int`] as special and use pre-made
|
|
// specialized constructor `CreateMinimalNegative()`
|
|
if (value < -maxInt) {
|
|
SetMinimalNegative();
|
|
return;
|
|
} else {
|
|
negative = true;
|
|
value *= -1;
|
|
}
|
|
}
|
|
if (value == 0) {
|
|
digits[0] = 0;
|
|
} else {
|
|
while (value > 0) {
|
|
divisionResult = __().math.IntegerDivision(value, 10);
|
|
value = divisionResult.quotient;
|
|
digits[digits.length] = divisionResult.remainder;
|
|
}
|
|
}
|
|
TrimLeadingZeroes();
|
|
}
|
|
|
|
/// Changes current value of [`BigInt`] to the value, given by decimal representation.
|
|
///
|
|
/// If `none` or invalid decimal representation (digits only, possibly with leading sign) is given
|
|
/// as an argument, caller's value won't change.
|
|
/// Returns `true` in case of success and `false` otherwise.
|
|
public final function bool SetDecimal(BaseText value) {
|
|
local int i;
|
|
local byte nextDigit;
|
|
local bool newNegative;
|
|
local array<byte> newDigits;
|
|
local Parser parser;
|
|
local Basetext.Character nextCharacter;
|
|
|
|
if (value == none) {
|
|
return false;
|
|
}
|
|
parser = value.Parse();
|
|
newNegative = ParseSign(parser);
|
|
// Reset to valid state whether sign was consumed or not
|
|
parser.Confirm();
|
|
parser.R();
|
|
newDigits.length = parser.GetRemainingLength();
|
|
// Parse new one
|
|
i = newDigits.length - 1;
|
|
while (!parser.HasFinished()){
|
|
// This should not happen, but just in case
|
|
if (i < 0) {
|
|
break;
|
|
}
|
|
parser.MCharacter(nextCharacter);
|
|
nextDigit = __().text.CharacterToInt(nextCharacter, 10);
|
|
if (nextDigit < 0) {
|
|
return false;
|
|
}
|
|
newDigits[i] = nextDigit;
|
|
i -= 1;
|
|
}
|
|
parser.FreeSelf();
|
|
digits = newDigits;
|
|
negative = newNegative;
|
|
TrimLeadingZeroes();
|
|
return true;
|
|
}
|
|
|
|
// Tries to parse either `+` or `-` and returns `true` iff it parsed `-`.
|
|
// If neither got parsed, `parser` will enter failed state.
|
|
// Assumes `parser` isn't `none`.
|
|
private final function bool ParseSign(Parser parser) {
|
|
parser.Match(P("-"));
|
|
negative = parser.Ok();
|
|
if (parser.Ok()) {
|
|
negative = true;
|
|
}
|
|
else {
|
|
parser.R();
|
|
parser.Match(P("+"));
|
|
}
|
|
return negative;
|
|
}
|
|
|
|
/// Changes current value of [`BigInt`] to the value, given by decimal representation.
|
|
///
|
|
/// If invalid decimal representation (digits only, possibly with leading sign) is given as
|
|
/// an argument, caller's value won't change.
|
|
/// Returns `true` in case of success and `false` otherwise.
|
|
public final function bool SetDecimal_S(string value) {
|
|
local bool result;
|
|
local MutableText wrapper;
|
|
|
|
wrapper = __().text.FromStringM(value);
|
|
result = SetDecimal(wrapper);
|
|
wrapper.FreeSelf();
|
|
return result;
|
|
}
|
|
|
|
// Auxiliary method for comparing two [`BigInt`]s by their absolute value.
|
|
private function BigIntCompareResult _compareAbsolute(BigInt other) {
|
|
local int i;
|
|
local array<byte> otherDigits;
|
|
|
|
otherDigits = other.digits;
|
|
if (digits.length == otherDigits.length)
|
|
{
|
|
for (i = digits.length - 1; i >= 0; i -= 1)
|
|
{
|
|
if (digits[i] < otherDigits[i]) {
|
|
return BICR_Less;
|
|
}
|
|
if (digits[i] > otherDigits[i]) {
|
|
return BICR_Greater;
|
|
}
|
|
}
|
|
return BICR_Equal;
|
|
}
|
|
if (digits.length < otherDigits.length) {
|
|
return BICR_Less;
|
|
}
|
|
return BICR_Greater;
|
|
}
|
|
|
|
/// Compares caller [`BigInt`] to [`other`].
|
|
///
|
|
/// [`BigIntCompareResult`] representing the result of comparison is returned as a result.
|
|
/// It describes how caller [`BigInt`] relates to the `other`, e.g. if `BICR_Less` was returned then
|
|
/// it means that caller [`BigInt`] is smaller that `other`.
|
|
/// If argument is `none`, then it is considered to be less ([`BICR_Less`]) than caller [`BigInt`].
|
|
public function BigIntCompareResult Compare(BigInt other) {
|
|
local BigIntCompareResult resultForModulus;
|
|
|
|
if (other == none) return BICR_Less;
|
|
if (negative && !other.negative) return BICR_Less;
|
|
if (!negative && other.negative) return BICR_Greater;
|
|
resultForModulus = _compareAbsolute(other);
|
|
if (resultForModulus == BICR_Equal) return BICR_Equal;
|
|
if (negative && (resultForModulus == BICR_Greater)) return BICR_Less;
|
|
if (!negative && (resultForModulus == BICR_Less)) return BICR_Less;
|
|
|
|
return BICR_Greater;
|
|
}
|
|
|
|
/// Compares caller [`BigInt`] to [`other`].
|
|
///
|
|
/// [`BigIntCompareResult`] representing the result of comparison is returned as a result.
|
|
/// It describes how caller [`BigInt`] relates to the `other`, e.g. if `BICR_Less` was returned then
|
|
/// it means that caller [`BigInt`] is smaller that `other`.
|
|
public function BigIntCompareResult CompareInt(int other) {
|
|
local BigInt wrapper;
|
|
local BigIntCompareResult result;
|
|
|
|
wrapper = _.math.ToBigInt(other);
|
|
result = Compare(wrapper);
|
|
wrapper.FreeSelf();
|
|
return result;
|
|
}
|
|
|
|
/// Compares caller [`BigInt`] to a decimal representation of a number.
|
|
///
|
|
/// [`BigIntCompareResult`] representing the result of comparison is returned as a result.
|
|
/// It describes how caller [`BigInt`] relates to the `other`, e.g. if `BICR_Less` was returned then
|
|
/// it means that caller [`BigInt`] is smaller that `other`.
|
|
/// If argument is `none` or is an invalid decimal representation (digits only, possibly with
|
|
/// leading sign, then it is considered to be less ([`BICR_Less`]) than caller [`BigInt`].
|
|
public function BigIntCompareResult CompareDecimal(BaseText other) {
|
|
local BigInt wrapper;
|
|
local BigIntCompareResult result;
|
|
|
|
wrapper = _.math.MakeBigInt(other);
|
|
result = Compare(wrapper);
|
|
_.memory.Free(wrapper);
|
|
return result;
|
|
}
|
|
|
|
/// Compares caller [`BigInt`] to a decimal representation of a number.
|
|
///
|
|
/// [`BigIntCompareResult`] representing the result of comparison is returned as a result.
|
|
/// It describes how caller [`BigInt`] relates to the `other`, e.g. if `BICR_Less` was returned then
|
|
/// it means that caller [`BigInt`] is smaller that `other`.
|
|
/// If argument is an invalid decimal representation (digits only, possibly with leading sign, then
|
|
/// it is considered to be less ([`BICR_Less`]) than caller [`BigInt`].
|
|
public function BigIntCompareResult CompareDecimal_S(string other) {
|
|
local BigInt wrapper;
|
|
local BigIntCompareResult result;
|
|
|
|
wrapper = _.math.MakeBigInt_S(other);
|
|
result = Compare(wrapper);
|
|
wrapper.FreeSelf();
|
|
return result;
|
|
}
|
|
|
|
// Adds absolute values of caller [`BigInt`] and [`other`] with no changes to the sign.
|
|
private function _add(BigInt other) {
|
|
local int i;
|
|
local byte carry, digitSum;
|
|
local array<byte> otherDigits;
|
|
|
|
if (other == none) {
|
|
return;
|
|
}
|
|
otherDigits = other.digits;
|
|
if (digits.length < otherDigits.length) {
|
|
digits.length = otherDigits.length;
|
|
} else {
|
|
otherDigits.length = digits.length;
|
|
}
|
|
carry = 0;
|
|
for (i = 0; i < digits.length; i += 1) {
|
|
digitSum = digits[i] + otherDigits[i] + carry;
|
|
digits[i] = _.math.Remainder(digitSum, 10);
|
|
carry = (digitSum - digits[i]) / 10;
|
|
}
|
|
if (carry > 0) {
|
|
digits[digits.length] = carry;
|
|
}
|
|
// No leading zeroes can be created here, so no need to trim
|
|
}
|
|
|
|
// Subtracts absolute value of [`other`] from the caller [`BigInt`], flipping caller's sign in case
|
|
// `other`'s absolute value is bigger.
|
|
private function _sub(BigInt other) {
|
|
local int i;
|
|
local int carry, nextDigit;
|
|
local array<byte> minuendDigits, subtrahendDigits;
|
|
local BigIntCompareResult resultForModulus;
|
|
|
|
if (other == none) {
|
|
return;
|
|
}
|
|
resultForModulus = _compareAbsolute(other);
|
|
if (resultForModulus == BICR_Equal) {
|
|
SetZero();
|
|
return;
|
|
}
|
|
if (resultForModulus == BICR_Less) {
|
|
negative = !negative;
|
|
minuendDigits = other.digits;
|
|
subtrahendDigits = digits;
|
|
} else {
|
|
minuendDigits = digits;
|
|
subtrahendDigits = other.digits;
|
|
}
|
|
digits.length = minuendDigits.length;
|
|
subtrahendDigits.length = minuendDigits.length;
|
|
carry = 0;
|
|
for (i = 0; i < digits.length; i += 1) {
|
|
nextDigit = int(minuendDigits[i]) - int(subtrahendDigits[i]) + carry;
|
|
if (nextDigit < 0) {
|
|
nextDigit += 10;
|
|
carry = -1;
|
|
} else {
|
|
carry = 0;
|
|
}
|
|
digits[i] = nextDigit;
|
|
}
|
|
TrimLeadingZeroes();
|
|
}
|
|
|
|
/// Adds another value to the caller [`BigInt`].
|
|
///
|
|
/// If argument is `none`, then given method does nothing.
|
|
public function Add(BigInt other) {
|
|
if (other == none) {
|
|
return;
|
|
}
|
|
if (negative == other.negative) {
|
|
_add(other);
|
|
} else {
|
|
_sub(other);
|
|
}
|
|
}
|
|
|
|
/// Adds another value to the caller [`BigInt`].
|
|
public function AddInt(int other) {
|
|
local BigInt otherObject;
|
|
|
|
otherObject = _.math.ToBigInt(other);
|
|
Add(otherObject);
|
|
_.memory.Free(otherObject);
|
|
}
|
|
|
|
/// Adds decimal representation of the number to the caller [`BigInt`].
|
|
///
|
|
/// If `none` or invalid decimal representation (digits only, possibly with leading sign) is given -
|
|
/// does nothing.
|
|
public function AddDecimal(BaseText other) {
|
|
local BigInt otherObject;
|
|
|
|
if (other == none) {
|
|
return;
|
|
}
|
|
otherObject = _.math.MakeBigInt(other);
|
|
Add(otherObject);
|
|
_.memory.Free(otherObject);
|
|
}
|
|
|
|
/// Adds decimal representation of the number to the caller [`BigInt`].
|
|
///
|
|
/// If invalid decimal representation (digits only, possibly with leading sign) is given -
|
|
/// does nothing.
|
|
public function AddDecimal_S(string other) {
|
|
local BigInt otherObject;
|
|
|
|
otherObject = _.math.MakeBigInt_S(other);
|
|
Add(otherObject);
|
|
_.memory.Free(otherObject);
|
|
}
|
|
|
|
/// Subtracts another value to the caller [`BigInt`].
|
|
///
|
|
/// If argument is `none`, then given method does nothing.
|
|
public function Subtract(BigInt other) {
|
|
if (negative != other.negative) {
|
|
_add(other);
|
|
} else {
|
|
_sub(other);
|
|
}
|
|
}
|
|
|
|
/// Adds another value to the caller [`BigInt`].
|
|
public function SubtractInt(int other) {
|
|
local BigInt otherObject;
|
|
|
|
otherObject = _.math.ToBigInt(other);
|
|
Subtract(otherObject);
|
|
_.memory.Free(otherObject);
|
|
}
|
|
|
|
/// Subtracts decimal representation of the number to the caller [`BigInt`].
|
|
///
|
|
/// If `none` or invalid decimal representation (digits only, possibly with leading sign) is given -
|
|
/// does nothing.
|
|
public function SubtractDecimal(BaseText other) {
|
|
local BigInt otherObject;
|
|
|
|
if (other == none) {
|
|
return;
|
|
}
|
|
otherObject = _.math.MakeBigInt(other);
|
|
Subtract(otherObject);
|
|
_.memory.Free(otherObject);
|
|
}
|
|
|
|
/// Adds decimal representation of the number to the caller [`BigInt`].
|
|
///
|
|
/// If invalid decimal representation (digits only, possibly with leading sign) is given -
|
|
/// does nothing.
|
|
public function SubtractDecimal_S(string other) {
|
|
local BigInt otherObject;
|
|
|
|
otherObject = _.math.MakeBigInt_S(other);
|
|
Subtract(otherObject);
|
|
_.memory.Free(otherObject);
|
|
}
|
|
|
|
/// Checks if caller [`BigInt`] is negative.
|
|
///
|
|
/// Returns if stored value is negative and `false` otherwise.
|
|
/// Zero is not considered negative number.
|
|
public function bool IsNegative() {
|
|
// Handle special case of zero first (it ignores `negative` flag)
|
|
if (digits.length == 1 && digits[0] == 0) {
|
|
return false;
|
|
}
|
|
return negative;
|
|
}
|
|
|
|
/// Converts caller [`BigInt`] into [`int`] representation.
|
|
///
|
|
/// In case stored value is outside `int`'s value range
|
|
/// (`[-maxInt-1, maxInt] == [-2147483648; 2147483647]`), method returns either maximal or minimal
|
|
// possible value, depending on the [`BigInt`]'s sign.
|
|
public function int ToInt() {
|
|
local int i;
|
|
local int accumulator;
|
|
local int safeDigitsAmount;
|
|
|
|
if (digits.length <= 0) {
|
|
return 0;
|
|
}
|
|
if (digits.length > DIGITS_IN_MAX_INT) {
|
|
if (negative) {
|
|
return (-maxInt - 1);
|
|
} else {
|
|
return maxInt;
|
|
}
|
|
}
|
|
// At most `DIGITS_IN_MAX_INT - 1` iterations
|
|
safeDigitsAmount = Min(DIGITS_IN_MAX_INT - 1, digits.length);
|
|
for (i = safeDigitsAmount - 1; i >= 0; i -= 1) {
|
|
accumulator *= 10;
|
|
accumulator += digits[i];
|
|
}
|
|
if (negative) {
|
|
accumulator *= -1;
|
|
}
|
|
accumulator = AddUnsafeDigitToInt(accumulator);
|
|
return accumulator;
|
|
}
|
|
|
|
/// Adding `DIGITS_IN_MAX_INT - 1` will never lead to an overflow, but adding the next digit can,
|
|
/// so we need to handle it differently and more carefully.
|
|
/// 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;
|
|
}
|
|
// Handle overflow
|
|
if (negative) {
|
|
return (-maxInt - 1);
|
|
}
|
|
return maxInt;
|
|
}
|
|
|
|
/// Converts caller [`BigInt`] into [`Text`] representation.
|
|
public function Text ToText() {
|
|
return ToText_M().IntoText();
|
|
}
|
|
|
|
/// Converts caller [`BigInt`] into [`MutableText`] representation.
|
|
public function MutableText ToText_M() {
|
|
local int i;
|
|
local MutableText result;
|
|
|
|
result = _.text.Empty();
|
|
if (negative) {
|
|
result.AppendCharacter(_.text.GetCharacter("-"));
|
|
}
|
|
for (i = digits.length - 1; i >= 0; i -= 1) {
|
|
result.AppendCharacter(_.text.CharacterFromCodePoint(digits[i] + 48));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// Converts caller [`BigInt`] into [`string`] representation.
|
|
public function string ToString() {
|
|
local int i;
|
|
local string result;
|
|
|
|
if (negative) {
|
|
result = "-";
|
|
}
|
|
for (i = digits.length - 1; i >= 0; i -= 1) {
|
|
result = result $ digits[i];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// Restores [`BigInt`] from the [`BigIntData`] value.
|
|
///
|
|
/// This method is created to make an efficient way to store [`BigInt`].
|
|
public function FromData(BigIntData data) {
|
|
local int i;
|
|
|
|
negative = data.negative;
|
|
digits = data.digits;
|
|
// Deal with possibly erroneous data
|
|
for (i = 0; i < digits.length; i += 1) {
|
|
if (digits[i] > 9) {
|
|
digits[i] = 9;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Converts caller [`BigInt`]'s value into [`BigIntData`].
|
|
///
|
|
/// This method is created to make an efficient way to store [`BigInt`].
|
|
public function BigIntData ToData() {
|
|
local BigIntData result;
|
|
|
|
result.negative = negative;
|
|
result.digits = digits;
|
|
return result;
|
|
}
|
|
|
|
defaultproperties {
|
|
} |