14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/js_bigint.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/global_env_constants-inl.h"
194514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value-inl.h"
204514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_number.h"
214514f5e3Sopenharmony_ci
224514f5e3Sopenharmony_cinamespace panda::ecmascript {
234514f5e3Sopenharmony_ciclass ObjectFactory;
244514f5e3Sopenharmony_ciconstexpr char dp[] = "0123456789abcdefghijklmnopqrstuvwxyz";
254514f5e3Sopenharmony_cistatic int CharToInt(char c)
264514f5e3Sopenharmony_ci{
274514f5e3Sopenharmony_ci    uint32_t res = 0;
284514f5e3Sopenharmony_ci    if (c >= '0' && c <= '9') {
294514f5e3Sopenharmony_ci        res = c - '0';
304514f5e3Sopenharmony_ci    } else if (c >= 'A' && c <= 'Z') {
314514f5e3Sopenharmony_ci        res = c - 'A' + 10; // 10:res must Greater than 10.
324514f5e3Sopenharmony_ci    } else if (c >= 'a' && c <= 'z') {
334514f5e3Sopenharmony_ci        res = c - 'a' + 10; // 10:res must Greater than 10
344514f5e3Sopenharmony_ci    }
354514f5e3Sopenharmony_ci    return static_cast<int>(res);
364514f5e3Sopenharmony_ci}
374514f5e3Sopenharmony_ci
384514f5e3Sopenharmony_cistatic void Division(CString &num, uint32_t conversionToRadix, uint32_t currentRadix, uint32_t &remain)
394514f5e3Sopenharmony_ci{
404514f5e3Sopenharmony_ci    ASSERT(conversionToRadix != 0);
414514f5e3Sopenharmony_ci    uint32_t temp = 0;
424514f5e3Sopenharmony_ci    remain = 0;
434514f5e3Sopenharmony_ci    for (size_t i = 0; i < num.size(); i++) {
444514f5e3Sopenharmony_ci        temp = (currentRadix * remain + static_cast<uint32_t>(CharToInt(num[i])));
454514f5e3Sopenharmony_ci        num[i] = dp[temp / conversionToRadix];
464514f5e3Sopenharmony_ci        remain = temp % conversionToRadix;
474514f5e3Sopenharmony_ci    }
484514f5e3Sopenharmony_ci    size_t count = 0;
494514f5e3Sopenharmony_ci    while (count < num.size() && num[count] == '0') {
504514f5e3Sopenharmony_ci        count++;
514514f5e3Sopenharmony_ci    }
524514f5e3Sopenharmony_ci    num = num.substr(count);
534514f5e3Sopenharmony_ci}
544514f5e3Sopenharmony_ci
554514f5e3Sopenharmony_ciCString BigIntHelper::Conversion(const CString &num, uint32_t conversionToRadix, uint32_t currentRadix)
564514f5e3Sopenharmony_ci{
574514f5e3Sopenharmony_ci    ASSERT(conversionToRadix != 0);
584514f5e3Sopenharmony_ci    CString newNum = num;
594514f5e3Sopenharmony_ci    CString res;
604514f5e3Sopenharmony_ci    uint32_t remain = 0;
614514f5e3Sopenharmony_ci    while (newNum.size() != 0) {
624514f5e3Sopenharmony_ci        Division(newNum, conversionToRadix, currentRadix, remain);
634514f5e3Sopenharmony_ci        res = dp[remain] + res;
644514f5e3Sopenharmony_ci    }
654514f5e3Sopenharmony_ci    return res;
664514f5e3Sopenharmony_ci}
674514f5e3Sopenharmony_ci
684514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::CreateUint64MaxBigInt(JSThread *thread)
694514f5e3Sopenharmony_ci{
704514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = CreateBigint(thread, 3); // 3:The number of digits in an object of type BigInt
714514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
724514f5e3Sopenharmony_ci    bigint->SetDigit(0, 0);
734514f5e3Sopenharmony_ci    bigint->SetDigit(1, 0);
744514f5e3Sopenharmony_ci    bigint->SetDigit(2, 1); // 2:The number of digits in an object of type BigInt
754514f5e3Sopenharmony_ci    return bigint;
764514f5e3Sopenharmony_ci}
774514f5e3Sopenharmony_ci
784514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::CreateInt64MaxBigInt(JSThread *thread)
794514f5e3Sopenharmony_ci{
804514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = CreateBigint(thread, 2); // 2:The number of digits in an object of type BigInt
814514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
824514f5e3Sopenharmony_ci    bigint->SetDigit(0, 0);
834514f5e3Sopenharmony_ci    bigint->SetDigit(1, 0x80000000); // 0x80000000:Int MAX
844514f5e3Sopenharmony_ci    return bigint;
854514f5e3Sopenharmony_ci}
864514f5e3Sopenharmony_ci
874514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::GetUint64MaxBigInt(JSThread *thread)
884514f5e3Sopenharmony_ci{
894514f5e3Sopenharmony_ci    return JSHandle<BigInt>::Cast(thread->GlobalConstants()->GetHandledUint64MaxBigInt());
904514f5e3Sopenharmony_ci}
914514f5e3Sopenharmony_ci
924514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::GetInt64MaxBigInt(JSThread *thread)
934514f5e3Sopenharmony_ci{
944514f5e3Sopenharmony_ci    return JSHandle<BigInt>::Cast(thread->GlobalConstants()->GetHandledInt64MaxBigInt());
954514f5e3Sopenharmony_ci}
964514f5e3Sopenharmony_ci
974514f5e3Sopenharmony_ciJSHandle<BigInt> BigIntHelper::SetBigInt(JSThread *thread, const CString &numStr, uint32_t currentRadix)
984514f5e3Sopenharmony_ci{
994514f5e3Sopenharmony_ci    int flag = 0;
1004514f5e3Sopenharmony_ci    if (numStr[0] == '-') {
1014514f5e3Sopenharmony_ci        flag = 1;
1024514f5e3Sopenharmony_ci    }
1034514f5e3Sopenharmony_ci
1044514f5e3Sopenharmony_ci    CString binaryStr = "";
1054514f5e3Sopenharmony_ci    if (currentRadix != BigInt::BINARY) {
1064514f5e3Sopenharmony_ci        binaryStr = Conversion(numStr.substr(flag), BigInt::BINARY, currentRadix);
1074514f5e3Sopenharmony_ci    } else {
1084514f5e3Sopenharmony_ci        binaryStr = numStr.substr(flag);
1094514f5e3Sopenharmony_ci    }
1104514f5e3Sopenharmony_ci
1114514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint;
1124514f5e3Sopenharmony_ci    size_t binaryStrLen = binaryStr.size();
1134514f5e3Sopenharmony_ci    size_t len = binaryStrLen / BigInt::DATEBITS;
1144514f5e3Sopenharmony_ci    size_t mod = binaryStrLen % BigInt::DATEBITS;
1154514f5e3Sopenharmony_ci    int index = 0;
1164514f5e3Sopenharmony_ci    if (mod == 0) {
1174514f5e3Sopenharmony_ci        index = static_cast<int>(len - 1);
1184514f5e3Sopenharmony_ci        bigint = BigInt::CreateBigint(thread, len);
1194514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
1204514f5e3Sopenharmony_ci    } else {
1214514f5e3Sopenharmony_ci        len++;
1224514f5e3Sopenharmony_ci        index = static_cast<int>(len - 1);
1234514f5e3Sopenharmony_ci        bigint = BigInt::CreateBigint(thread, len);
1244514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
1254514f5e3Sopenharmony_ci        uint32_t val = 0;
1264514f5e3Sopenharmony_ci        for (size_t i = 0; i < mod; ++i) {
1274514f5e3Sopenharmony_ci            val <<= 1;
1284514f5e3Sopenharmony_ci            val |= static_cast<uint32_t>(binaryStr[i] - '0');
1294514f5e3Sopenharmony_ci        }
1304514f5e3Sopenharmony_ci        bigint->SetDigit(index, val);
1314514f5e3Sopenharmony_ci        index--;
1324514f5e3Sopenharmony_ci    }
1334514f5e3Sopenharmony_ci    if (flag == 1) {
1344514f5e3Sopenharmony_ci        bigint->SetSign(true);
1354514f5e3Sopenharmony_ci    }
1364514f5e3Sopenharmony_ci    size_t i = mod;
1374514f5e3Sopenharmony_ci    while (i < binaryStrLen) {
1384514f5e3Sopenharmony_ci        uint32_t val = 0;
1394514f5e3Sopenharmony_ci        for (size_t j = 0; j < BigInt::DATEBITS && i < binaryStrLen; ++j, ++i) {
1404514f5e3Sopenharmony_ci            val <<= 1;
1414514f5e3Sopenharmony_ci            val |= static_cast<uint32_t>(binaryStr[i] - '0');
1424514f5e3Sopenharmony_ci        }
1434514f5e3Sopenharmony_ci        bigint->SetDigit(index, val);
1444514f5e3Sopenharmony_ci        index--;
1454514f5e3Sopenharmony_ci    }
1464514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, bigint);
1474514f5e3Sopenharmony_ci}
1484514f5e3Sopenharmony_ci
1494514f5e3Sopenharmony_ciJSHandle<BigInt> BigIntHelper::RightTruncate(JSThread *thread, JSHandle<BigInt> x)
1504514f5e3Sopenharmony_ci{
1514514f5e3Sopenharmony_ci    int len = static_cast<int>(x->GetLength());
1524514f5e3Sopenharmony_ci    ASSERT(len != 0);
1534514f5e3Sopenharmony_ci    if (len == 1 && x->GetDigit(0) == 0) {
1544514f5e3Sopenharmony_ci        x->SetSign(false);
1554514f5e3Sopenharmony_ci        return x;
1564514f5e3Sopenharmony_ci    }
1574514f5e3Sopenharmony_ci    int index = len - 1;
1584514f5e3Sopenharmony_ci    if (x->GetDigit(index) != 0) {
1594514f5e3Sopenharmony_ci        return x;
1604514f5e3Sopenharmony_ci    }
1614514f5e3Sopenharmony_ci    while (index >= 0) {
1624514f5e3Sopenharmony_ci        if (x->GetDigit(index) != 0) {
1634514f5e3Sopenharmony_ci            break;
1644514f5e3Sopenharmony_ci        }
1654514f5e3Sopenharmony_ci        index--;
1664514f5e3Sopenharmony_ci    }
1674514f5e3Sopenharmony_ci
1684514f5e3Sopenharmony_ci    if (index == -1) {
1694514f5e3Sopenharmony_ci        return BigInt::Int32ToBigInt(thread, 0);
1704514f5e3Sopenharmony_ci    } else {
1714514f5e3Sopenharmony_ci        ASSERT(index >= 0);
1724514f5e3Sopenharmony_ci        return BigInt::Copy(thread, x, index + 1);
1734514f5e3Sopenharmony_ci    }
1744514f5e3Sopenharmony_ci}
1754514f5e3Sopenharmony_ci
1764514f5e3Sopenharmony_ciCString BigIntHelper::GetBinary(const BigInt *bigint)
1774514f5e3Sopenharmony_ci{
1784514f5e3Sopenharmony_ci    ASSERT(bigint != nullptr);
1794514f5e3Sopenharmony_ci    int index = 0;
1804514f5e3Sopenharmony_ci    int len = static_cast<int>(bigint->GetLength());
1814514f5e3Sopenharmony_ci    int strLen = BigInt::DATEBITS * len;
1824514f5e3Sopenharmony_ci    CString res(strLen, '0');
1834514f5e3Sopenharmony_ci    int strIndex = strLen - 1;
1844514f5e3Sopenharmony_ci    while (index < len) {
1854514f5e3Sopenharmony_ci        int bityLen = BigInt::DATEBITS;
1864514f5e3Sopenharmony_ci        uint32_t val = bigint->GetDigit(index);
1874514f5e3Sopenharmony_ci        while (bityLen--) {
1884514f5e3Sopenharmony_ci            res[strIndex--] = (val & 1) + '0';
1894514f5e3Sopenharmony_ci            val = val >> 1;
1904514f5e3Sopenharmony_ci        }
1914514f5e3Sopenharmony_ci        index++;
1924514f5e3Sopenharmony_ci    }
1934514f5e3Sopenharmony_ci    DeZero(res);
1944514f5e3Sopenharmony_ci    return res;
1954514f5e3Sopenharmony_ci}
1964514f5e3Sopenharmony_ci
1974514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::CreateBigint(JSThread *thread, uint32_t length)
1984514f5e3Sopenharmony_ci{
1994514f5e3Sopenharmony_ci    if (length > MAXSIZE) {
2004514f5e3Sopenharmony_ci        JSHandle<BigInt> bigint(thread, JSTaggedValue::Exception());
2014514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "Maximum BigInt size exceeded", bigint);
2024514f5e3Sopenharmony_ci    }
2034514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2044514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = factory->NewBigInt(length);
2054514f5e3Sopenharmony_ci    return bigint;
2064514f5e3Sopenharmony_ci}
2074514f5e3Sopenharmony_ci
2084514f5e3Sopenharmony_ci// 6.1.6.2.13
2094514f5e3Sopenharmony_cibool BigInt::Equal(const JSTaggedValue &x, const JSTaggedValue &y)
2104514f5e3Sopenharmony_ci{
2114514f5e3Sopenharmony_ci    BigInt* xVal = BigInt::Cast(x.GetTaggedObject());
2124514f5e3Sopenharmony_ci    BigInt* yVal = BigInt::Cast(y.GetTaggedObject());
2134514f5e3Sopenharmony_ci    return Equal(xVal, yVal);
2144514f5e3Sopenharmony_ci}
2154514f5e3Sopenharmony_ci
2164514f5e3Sopenharmony_cibool BigInt::Equal(const BigInt *x, const BigInt *y)
2174514f5e3Sopenharmony_ci{
2184514f5e3Sopenharmony_ci    ASSERT(x != nullptr);
2194514f5e3Sopenharmony_ci    ASSERT(y != nullptr);
2204514f5e3Sopenharmony_ci    if (x->GetSign() != y->GetSign() || x->GetLength() != y->GetLength()) {
2214514f5e3Sopenharmony_ci        return false;
2224514f5e3Sopenharmony_ci    }
2234514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < x->GetLength(); ++i) {
2244514f5e3Sopenharmony_ci        if (x->GetDigit(i) != y->GetDigit(i)) {
2254514f5e3Sopenharmony_ci            return false;
2264514f5e3Sopenharmony_ci        }
2274514f5e3Sopenharmony_ci    }
2284514f5e3Sopenharmony_ci    return true;
2294514f5e3Sopenharmony_ci}
2304514f5e3Sopenharmony_ci
2314514f5e3Sopenharmony_ci// 6.1.6.2.14
2324514f5e3Sopenharmony_cibool BigInt::SameValue(const JSTaggedValue &x, const JSTaggedValue &y)
2334514f5e3Sopenharmony_ci{
2344514f5e3Sopenharmony_ci    return Equal(x, y);
2354514f5e3Sopenharmony_ci}
2364514f5e3Sopenharmony_ci
2374514f5e3Sopenharmony_ci// 6.1.6.2.15
2384514f5e3Sopenharmony_cibool BigInt::SameValueZero(const JSTaggedValue &x, const JSTaggedValue &y)
2394514f5e3Sopenharmony_ci{
2404514f5e3Sopenharmony_ci    return Equal(x, y);
2414514f5e3Sopenharmony_ci}
2424514f5e3Sopenharmony_ci
2434514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::BitwiseOp(JSThread *thread, Operate op, JSHandle<BigInt> x, JSHandle<BigInt> y)
2444514f5e3Sopenharmony_ci{
2454514f5e3Sopenharmony_ci    uint32_t maxLen = 0;
2464514f5e3Sopenharmony_ci    uint32_t minLen = 0;
2474514f5e3Sopenharmony_ci    uint32_t xlen = x->GetLength();
2484514f5e3Sopenharmony_ci    uint32_t ylen = y->GetLength();
2494514f5e3Sopenharmony_ci    if (xlen > ylen) {
2504514f5e3Sopenharmony_ci        maxLen = xlen;
2514514f5e3Sopenharmony_ci        minLen = ylen;
2524514f5e3Sopenharmony_ci    } else {
2534514f5e3Sopenharmony_ci        maxLen = ylen;
2544514f5e3Sopenharmony_ci        minLen = xlen;
2554514f5e3Sopenharmony_ci    }
2564514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = BigInt::CreateBigint(thread, maxLen);
2574514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
2584514f5e3Sopenharmony_ci    for (size_t i = 0; i < minLen; ++i) {
2594514f5e3Sopenharmony_ci        if (op == Operate::OR) {
2604514f5e3Sopenharmony_ci            bigint->SetDigit(i, x->GetDigit(i) | y->GetDigit(i));
2614514f5e3Sopenharmony_ci        } else if (op == Operate::AND) {
2624514f5e3Sopenharmony_ci            bigint->SetDigit(i, x->GetDigit(i) & y->GetDigit(i));
2634514f5e3Sopenharmony_ci        } else {
2644514f5e3Sopenharmony_ci            ASSERT(op == Operate::XOR);
2654514f5e3Sopenharmony_ci            bigint->SetDigit(i, x->GetDigit(i) ^ y->GetDigit(i));
2664514f5e3Sopenharmony_ci        }
2674514f5e3Sopenharmony_ci    }
2684514f5e3Sopenharmony_ci    if (op == Operate::OR || op == Operate::XOR) {
2694514f5e3Sopenharmony_ci        if (xlen > ylen) {
2704514f5e3Sopenharmony_ci            for (size_t i = ylen; i < xlen; ++i) {
2714514f5e3Sopenharmony_ci                bigint->SetDigit(i, x->GetDigit(i));
2724514f5e3Sopenharmony_ci            }
2734514f5e3Sopenharmony_ci        } else if (ylen > xlen) {
2744514f5e3Sopenharmony_ci            for (size_t i = xlen; i < ylen; ++i) {
2754514f5e3Sopenharmony_ci                bigint->SetDigit(i, y->GetDigit(i));
2764514f5e3Sopenharmony_ci            }
2774514f5e3Sopenharmony_ci        }
2784514f5e3Sopenharmony_ci    }
2794514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, bigint);
2804514f5e3Sopenharmony_ci}
2814514f5e3Sopenharmony_ci
2824514f5e3Sopenharmony_ciJSHandle<BigInt> OneIsNegativeAND(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
2834514f5e3Sopenharmony_ci{
2844514f5e3Sopenharmony_ci    JSHandle<BigInt> yVal = BigInt::BitwiseSubOne(thread, y, y->GetLength());
2854514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
2864514f5e3Sopenharmony_ci    uint32_t xLength = x->GetLength();
2874514f5e3Sopenharmony_ci    uint32_t yLength = yVal->GetLength();
2884514f5e3Sopenharmony_ci    uint32_t minLen = xLength;
2894514f5e3Sopenharmony_ci    if (xLength > yLength) {
2904514f5e3Sopenharmony_ci        minLen = yLength;
2914514f5e3Sopenharmony_ci    }
2924514f5e3Sopenharmony_ci    JSHandle<BigInt> newBigint = BigInt::CreateBigint(thread, xLength);
2934514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
2944514f5e3Sopenharmony_ci    uint32_t i = 0;
2954514f5e3Sopenharmony_ci    while (i < minLen) {
2964514f5e3Sopenharmony_ci        uint32_t res = x->GetDigit(i) & ~(yVal->GetDigit(i));
2974514f5e3Sopenharmony_ci        newBigint->SetDigit(i, res);
2984514f5e3Sopenharmony_ci        ++i;
2994514f5e3Sopenharmony_ci    }
3004514f5e3Sopenharmony_ci    while (i < xLength) {
3014514f5e3Sopenharmony_ci        newBigint->SetDigit(i, x->GetDigit(i));
3024514f5e3Sopenharmony_ci        ++i;
3034514f5e3Sopenharmony_ci    }
3044514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, newBigint);
3054514f5e3Sopenharmony_ci}
3064514f5e3Sopenharmony_ci
3074514f5e3Sopenharmony_ci// 6.1.6.2.20 BigInt::bitwiseAND ( x, y )
3084514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::BitwiseAND(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
3094514f5e3Sopenharmony_ci{
3104514f5e3Sopenharmony_ci    if (x->GetSign() && y->GetSign()) {
3114514f5e3Sopenharmony_ci        // (-x) & (-y) == -(((x-1) | (y-1)) + 1)
3124514f5e3Sopenharmony_ci        JSHandle<BigInt> xVal = BitwiseSubOne(thread, x, x->GetLength());
3134514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
3144514f5e3Sopenharmony_ci        JSHandle<BigInt> yVal = BitwiseSubOne(thread, y, y->GetLength());
3154514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
3164514f5e3Sopenharmony_ci        JSHandle<BigInt> temp = BitwiseOp(thread, Operate::OR, xVal, yVal);
3174514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
3184514f5e3Sopenharmony_ci        JSHandle<BigInt> res = BitwiseAddOne(thread, temp);
3194514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
3204514f5e3Sopenharmony_ci        return res;
3214514f5e3Sopenharmony_ci    }
3224514f5e3Sopenharmony_ci    if (x->GetSign() != y->GetSign()) {
3234514f5e3Sopenharmony_ci        // x & (-y) == x & ~(y-1)
3244514f5e3Sopenharmony_ci        if (!x->GetSign()) {
3254514f5e3Sopenharmony_ci            return OneIsNegativeAND(thread, x, y);
3264514f5e3Sopenharmony_ci        } else {
3274514f5e3Sopenharmony_ci            return OneIsNegativeAND(thread, y, x);
3284514f5e3Sopenharmony_ci        }
3294514f5e3Sopenharmony_ci    }
3304514f5e3Sopenharmony_ci    return BitwiseOp(thread, Operate::AND, x, y);
3314514f5e3Sopenharmony_ci}
3324514f5e3Sopenharmony_ci
3334514f5e3Sopenharmony_ciJSHandle<BigInt> OneIsNegativeXOR(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
3344514f5e3Sopenharmony_ci{
3354514f5e3Sopenharmony_ci    JSHandle<BigInt> yVal = BigInt::BitwiseSubOne(thread, y, y->GetLength());
3364514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
3374514f5e3Sopenharmony_ci    JSHandle<BigInt> temp = BigInt::BitwiseOp(thread, Operate::XOR, x, yVal);
3384514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
3394514f5e3Sopenharmony_ci    JSHandle<BigInt> res = BigInt::BitwiseAddOne(thread, temp);
3404514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
3414514f5e3Sopenharmony_ci    return res;
3424514f5e3Sopenharmony_ci}
3434514f5e3Sopenharmony_ci
3444514f5e3Sopenharmony_ci// 6.1.6.2.21 BigInt::bitwiseOR ( x, y )
3454514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::BitwiseXOR(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
3464514f5e3Sopenharmony_ci{
3474514f5e3Sopenharmony_ci    if (x->GetSign() && y->GetSign()) {
3484514f5e3Sopenharmony_ci        // (-x) ^ (-y) == (x-1) ^ (y-1)
3494514f5e3Sopenharmony_ci        JSHandle<BigInt> xVal = BitwiseSubOne(thread, x, x->GetLength());
3504514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
3514514f5e3Sopenharmony_ci        JSHandle<BigInt> yVal = BitwiseSubOne(thread, y, y->GetLength());
3524514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
3534514f5e3Sopenharmony_ci        return BitwiseOp(thread, Operate::XOR, xVal, yVal);
3544514f5e3Sopenharmony_ci    }
3554514f5e3Sopenharmony_ci    if (x->GetSign() != y->GetSign()) {
3564514f5e3Sopenharmony_ci        // x ^ (-y) == -((x ^ (y-1)) + 1)
3574514f5e3Sopenharmony_ci        if (!x->GetSign()) {
3584514f5e3Sopenharmony_ci            return OneIsNegativeXOR(thread, x, y);
3594514f5e3Sopenharmony_ci        } else {
3604514f5e3Sopenharmony_ci            return OneIsNegativeXOR(thread, y, x);
3614514f5e3Sopenharmony_ci        }
3624514f5e3Sopenharmony_ci    }
3634514f5e3Sopenharmony_ci    return BitwiseOp(thread, Operate::XOR, x, y);
3644514f5e3Sopenharmony_ci}
3654514f5e3Sopenharmony_ci
3664514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::BitwiseSubOne(JSThread *thread, JSHandle<BigInt> bigint, uint32_t maxLen)
3674514f5e3Sopenharmony_ci{
3684514f5e3Sopenharmony_ci    ASSERT(!bigint->IsZero());
3694514f5e3Sopenharmony_ci    ASSERT(maxLen >= bigint->GetLength());
3704514f5e3Sopenharmony_ci
3714514f5e3Sopenharmony_ci    JSHandle<BigInt> newBigint = BigInt::CreateBigint(thread, maxLen);
3724514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
3734514f5e3Sopenharmony_ci    uint32_t bigintLen = bigint->GetLength();
3744514f5e3Sopenharmony_ci    uint32_t carry = 1;
3754514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < bigintLen; i++) {
3764514f5e3Sopenharmony_ci        uint32_t bigintCarry = 0;
3774514f5e3Sopenharmony_ci        newBigint->SetDigit(i, BigIntHelper::SubHelper(bigint->GetDigit(i), carry, bigintCarry));
3784514f5e3Sopenharmony_ci        carry = bigintCarry;
3794514f5e3Sopenharmony_ci    }
3804514f5e3Sopenharmony_ci    ASSERT(!carry);
3814514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, newBigint);
3824514f5e3Sopenharmony_ci}
3834514f5e3Sopenharmony_ci
3844514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::BitwiseAddOne(JSThread *thread, JSHandle<BigInt> bigint)
3854514f5e3Sopenharmony_ci{
3864514f5e3Sopenharmony_ci    uint32_t bigintLength = bigint->GetLength();
3874514f5e3Sopenharmony_ci
3884514f5e3Sopenharmony_ci    bool needExpend = true;
3894514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < bigintLength; i++) {
3904514f5e3Sopenharmony_ci        if (std::numeric_limits<uint32_t>::max() != bigint->GetDigit(i)) {
3914514f5e3Sopenharmony_ci            needExpend = false;
3924514f5e3Sopenharmony_ci            break;
3934514f5e3Sopenharmony_ci        }
3944514f5e3Sopenharmony_ci    }
3954514f5e3Sopenharmony_ci    uint32_t newLength = bigintLength;
3964514f5e3Sopenharmony_ci    if (needExpend) {
3974514f5e3Sopenharmony_ci        newLength += 1;
3984514f5e3Sopenharmony_ci    }
3994514f5e3Sopenharmony_ci    JSHandle<BigInt> newBigint = BigInt::CreateBigint(thread, newLength);
4004514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
4014514f5e3Sopenharmony_ci    uint32_t carry = 1;
4024514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < bigintLength; i++) {
4034514f5e3Sopenharmony_ci        uint32_t bigintCarry = 0;
4044514f5e3Sopenharmony_ci        newBigint->SetDigit(i, BigIntHelper::AddHelper(bigint->GetDigit(i), carry, bigintCarry));
4054514f5e3Sopenharmony_ci        carry = bigintCarry;
4064514f5e3Sopenharmony_ci    }
4074514f5e3Sopenharmony_ci    if (needExpend) {
4084514f5e3Sopenharmony_ci        newBigint->SetDigit(bigintLength, carry);
4094514f5e3Sopenharmony_ci    }
4104514f5e3Sopenharmony_ci    newBigint->SetSign(true);
4114514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, newBigint);
4124514f5e3Sopenharmony_ci}
4134514f5e3Sopenharmony_ci
4144514f5e3Sopenharmony_ciJSHandle<BigInt> OneIsNegativeOR(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
4154514f5e3Sopenharmony_ci{
4164514f5e3Sopenharmony_ci    uint32_t xLength = x->GetLength();
4174514f5e3Sopenharmony_ci    uint32_t maxLen = xLength;
4184514f5e3Sopenharmony_ci    if (maxLen < y->GetLength()) {
4194514f5e3Sopenharmony_ci        maxLen = y->GetLength();
4204514f5e3Sopenharmony_ci    }
4214514f5e3Sopenharmony_ci    JSHandle<BigInt> yVal = BigInt::BitwiseSubOne(thread, y, maxLen);
4224514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
4234514f5e3Sopenharmony_ci    uint32_t yLength = yVal->GetLength();
4244514f5e3Sopenharmony_ci    uint32_t minLen = xLength;
4254514f5e3Sopenharmony_ci    if (minLen > yLength) {
4264514f5e3Sopenharmony_ci        minLen = yLength;
4274514f5e3Sopenharmony_ci    }
4284514f5e3Sopenharmony_ci    JSHandle<BigInt> newBigint = BigInt::CreateBigint(thread, yLength);
4294514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
4304514f5e3Sopenharmony_ci    uint32_t i = 0;
4314514f5e3Sopenharmony_ci    while (i < minLen) {
4324514f5e3Sopenharmony_ci        uint32_t res = ~(x->GetDigit(i)) & yVal->GetDigit(i);
4334514f5e3Sopenharmony_ci        newBigint->SetDigit(i, res);
4344514f5e3Sopenharmony_ci        ++i;
4354514f5e3Sopenharmony_ci    }
4364514f5e3Sopenharmony_ci    while (i < yLength) {
4374514f5e3Sopenharmony_ci        newBigint->SetDigit(i, yVal->GetDigit(i));
4384514f5e3Sopenharmony_ci        ++i;
4394514f5e3Sopenharmony_ci    }
4404514f5e3Sopenharmony_ci    JSHandle<BigInt> temp = BigIntHelper::RightTruncate(thread, newBigint);
4414514f5e3Sopenharmony_ci    JSHandle<BigInt> res = BigInt::BitwiseAddOne(thread, temp);
4424514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
4434514f5e3Sopenharmony_ci    res->SetSign(true);
4444514f5e3Sopenharmony_ci    return res;
4454514f5e3Sopenharmony_ci}
4464514f5e3Sopenharmony_ci
4474514f5e3Sopenharmony_ci// 6.1.6.2.22 BigInt::bitwiseOR ( x, y )
4484514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::BitwiseOR(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
4494514f5e3Sopenharmony_ci{
4504514f5e3Sopenharmony_ci    if (x->GetSign() && y->GetSign()) {
4514514f5e3Sopenharmony_ci        // (-x) | (-y) == -(((x-1) & (y-1)) + 1)
4524514f5e3Sopenharmony_ci        uint32_t maxLen = x->GetLength();
4534514f5e3Sopenharmony_ci        uint32_t yLen = y->GetLength();
4544514f5e3Sopenharmony_ci        maxLen < yLen ? maxLen = yLen : 0;
4554514f5e3Sopenharmony_ci        JSHandle<BigInt> xVal = BitwiseSubOne(thread, x, maxLen);
4564514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
4574514f5e3Sopenharmony_ci        JSHandle<BigInt> yVal = BitwiseSubOne(thread, y, yLen);
4584514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
4594514f5e3Sopenharmony_ci        JSHandle<BigInt> temp = BitwiseOp(thread, Operate::AND, xVal, yVal);
4604514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
4614514f5e3Sopenharmony_ci        JSHandle<BigInt> res = BitwiseAddOne(thread, temp);
4624514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
4634514f5e3Sopenharmony_ci        res->SetSign(true);
4644514f5e3Sopenharmony_ci        return res;
4654514f5e3Sopenharmony_ci    }
4664514f5e3Sopenharmony_ci    if (x->GetSign() != y->GetSign()) {
4674514f5e3Sopenharmony_ci        // x | (-y) == -(((y-1) & ~x) + 1)
4684514f5e3Sopenharmony_ci        if (!x->GetSign()) {
4694514f5e3Sopenharmony_ci            return OneIsNegativeOR(thread, x, y);
4704514f5e3Sopenharmony_ci        } else {
4714514f5e3Sopenharmony_ci            return OneIsNegativeOR(thread, y, x);
4724514f5e3Sopenharmony_ci        }
4734514f5e3Sopenharmony_ci    }
4744514f5e3Sopenharmony_ci    return BitwiseOp(thread, Operate::OR, x, y);
4754514f5e3Sopenharmony_ci}
4764514f5e3Sopenharmony_ci
4774514f5e3Sopenharmony_ci// 6.1.6.2.23 BigInt::toString ( x )
4784514f5e3Sopenharmony_ciJSHandle<EcmaString> BigInt::ToString(JSThread *thread, JSHandle<BigInt> bigint, uint32_t conversionToRadix)
4794514f5e3Sopenharmony_ci{
4804514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
4814514f5e3Sopenharmony_ci    CString result = bigint->ToStdString(conversionToRadix);
4824514f5e3Sopenharmony_ci    return factory->NewFromASCII(result.c_str());
4834514f5e3Sopenharmony_ci}
4844514f5e3Sopenharmony_ci
4854514f5e3Sopenharmony_ciCString BigInt::ToStdString(uint32_t conversionToRadix) const
4864514f5e3Sopenharmony_ci{
4874514f5e3Sopenharmony_ci    CString result =
4884514f5e3Sopenharmony_ci        BigIntHelper::Conversion(BigIntHelper::GetBinary(this), conversionToRadix, BINARY);
4894514f5e3Sopenharmony_ci    if (GetSign()) {
4904514f5e3Sopenharmony_ci        result = "-" + result;
4914514f5e3Sopenharmony_ci    }
4924514f5e3Sopenharmony_ci    return result;
4934514f5e3Sopenharmony_ci}
4944514f5e3Sopenharmony_ci
4954514f5e3Sopenharmony_ciJSTaggedValue BigInt::NumberToBigInt(JSThread *thread, JSHandle<JSTaggedValue> number)
4964514f5e3Sopenharmony_ci{
4974514f5e3Sopenharmony_ci    if (!number->IsInteger()) {
4984514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "The number cannot be converted to a BigInt because it is not an integer",
4994514f5e3Sopenharmony_ci                                     JSTaggedValue::Exception());
5004514f5e3Sopenharmony_ci    }
5014514f5e3Sopenharmony_ci    double num = number->GetNumber();
5024514f5e3Sopenharmony_ci    if (num == 0.0) {
5034514f5e3Sopenharmony_ci        return Int32ToBigInt(thread, 0).GetTaggedValue();
5044514f5e3Sopenharmony_ci    }
5054514f5e3Sopenharmony_ci    return DoubleToBigInt(thread, num);
5064514f5e3Sopenharmony_ci}
5074514f5e3Sopenharmony_ci
5084514f5e3Sopenharmony_ciJSTaggedValue BigInt::DoubleToBigInt(JSThread *thread, double num)
5094514f5e3Sopenharmony_ci{
5104514f5e3Sopenharmony_ci    // Bit operations must be of integer type
5114514f5e3Sopenharmony_ci    uint64_t bits = 0;
5124514f5e3Sopenharmony_ci    if (memcpy_s(&bits, sizeof(bits), &num, sizeof(num)) != EOK) {
5134514f5e3Sopenharmony_ci        LOG_FULL(FATAL) << "memcpy_s failed";
5144514f5e3Sopenharmony_ci        UNREACHABLE();
5154514f5e3Sopenharmony_ci    }
5164514f5e3Sopenharmony_ci    // Take out bits 62-52 (11 bits in total) and subtract 1023
5174514f5e3Sopenharmony_ci    uint64_t integerDigits = ((bits >> base::DOUBLE_SIGNIFICAND_SIZE) & 0x7FF) - base::DOUBLE_EXPONENT_BIAS;
5184514f5e3Sopenharmony_ci    uint32_t mayNeedLen = integerDigits / DATEBITS + 1;
5194514f5e3Sopenharmony_ci
5204514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = CreateBigint(thread, mayNeedLen);
5214514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
5224514f5e3Sopenharmony_ci    bigint->SetSign(num < 0);
5234514f5e3Sopenharmony_ci    uint64_t mantissa = (bits & base::DOUBLE_SIGNIFICAND_MASK) | base::DOUBLE_HIDDEN_BIT;
5244514f5e3Sopenharmony_ci    int mantissaSize = base::DOUBLE_SIGNIFICAND_SIZE;
5254514f5e3Sopenharmony_ci
5264514f5e3Sopenharmony_ci    int leftover = 0;
5274514f5e3Sopenharmony_ci    bool isFirstInto = true;
5284514f5e3Sopenharmony_ci    for (int index = static_cast<int>(mayNeedLen - 1); index >= 0; --index) {
5294514f5e3Sopenharmony_ci        uint32_t doubleNum = 0;
5304514f5e3Sopenharmony_ci        if (isFirstInto) {
5314514f5e3Sopenharmony_ci            isFirstInto = false;
5324514f5e3Sopenharmony_ci            leftover = mantissaSize - static_cast<int>(integerDigits % DATEBITS);
5334514f5e3Sopenharmony_ci            doubleNum = static_cast<uint32_t>(mantissa >> leftover);
5344514f5e3Sopenharmony_ci            mantissa = mantissa << (64 - leftover); // 64 : double bits size
5354514f5e3Sopenharmony_ci            bigint->SetDigit(index, doubleNum);
5364514f5e3Sopenharmony_ci        } else {
5374514f5e3Sopenharmony_ci            leftover -= DATEBITS;
5384514f5e3Sopenharmony_ci            doubleNum = static_cast<uint32_t>(mantissa >> DATEBITS);
5394514f5e3Sopenharmony_ci            mantissa = mantissa << DATEBITS;
5404514f5e3Sopenharmony_ci            bigint->SetDigit(index, doubleNum);
5414514f5e3Sopenharmony_ci        }
5424514f5e3Sopenharmony_ci    }
5434514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, bigint).GetTaggedValue();
5444514f5e3Sopenharmony_ci}
5454514f5e3Sopenharmony_ci
5464514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::Int32ToBigInt(JSThread *thread, const int &number)
5474514f5e3Sopenharmony_ci{
5484514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = CreateBigint(thread, 1);
5494514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
5504514f5e3Sopenharmony_ci    uint32_t value = 0;
5514514f5e3Sopenharmony_ci    bool sign = number < 0;
5524514f5e3Sopenharmony_ci    if (sign) {
5534514f5e3Sopenharmony_ci        value = static_cast<uint32_t>(-(number + 1)) + 1;
5544514f5e3Sopenharmony_ci    } else {
5554514f5e3Sopenharmony_ci        value = number;
5564514f5e3Sopenharmony_ci    }
5574514f5e3Sopenharmony_ci    bigint->SetDigit(0, value);
5584514f5e3Sopenharmony_ci    bigint->SetSign(sign);
5594514f5e3Sopenharmony_ci    return bigint;
5604514f5e3Sopenharmony_ci}
5614514f5e3Sopenharmony_ci
5624514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::Uint32ToBigInt(JSThread *thread, const uint32_t &number)
5634514f5e3Sopenharmony_ci{
5644514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = CreateBigint(thread, 1);
5654514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
5664514f5e3Sopenharmony_ci    bigint->SetDigit(0, number);
5674514f5e3Sopenharmony_ci    return bigint;
5684514f5e3Sopenharmony_ci}
5694514f5e3Sopenharmony_ci
5704514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::Int64ToBigInt(JSThread *thread, const int64_t &number)
5714514f5e3Sopenharmony_ci{
5724514f5e3Sopenharmony_ci    uint64_t value = 0;
5734514f5e3Sopenharmony_ci    bool sign = number < 0;
5744514f5e3Sopenharmony_ci    if (sign) {
5754514f5e3Sopenharmony_ci        value = static_cast<uint64_t>(-(number + 1)) + 1;
5764514f5e3Sopenharmony_ci    } else {
5774514f5e3Sopenharmony_ci        value = number;
5784514f5e3Sopenharmony_ci    }
5794514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = Uint64ToBigInt(thread, value);
5804514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
5814514f5e3Sopenharmony_ci    bigint->SetSign(sign);
5824514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, bigint);
5834514f5e3Sopenharmony_ci}
5844514f5e3Sopenharmony_ci
5854514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::Uint64ToBigInt(JSThread *thread, const uint64_t &number)
5864514f5e3Sopenharmony_ci{
5874514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = CreateBigint(thread, 2); // 2 : one int64_t bits need two uint32_t bits
5884514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
5894514f5e3Sopenharmony_ci    uint32_t lowBits = static_cast<uint32_t>(number & 0xffffffff);
5904514f5e3Sopenharmony_ci    uint32_t highBits = static_cast<uint32_t>((number >> DATEBITS) & 0xffffffff);
5914514f5e3Sopenharmony_ci    bigint->SetDigit(0, lowBits);
5924514f5e3Sopenharmony_ci    bigint->SetDigit(1, highBits);
5934514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, bigint);
5944514f5e3Sopenharmony_ci}
5954514f5e3Sopenharmony_ci
5964514f5e3Sopenharmony_ciuint64_t BigInt::ToUint64()
5974514f5e3Sopenharmony_ci{
5984514f5e3Sopenharmony_ci    uint32_t len = GetLength();
5994514f5e3Sopenharmony_ci    ASSERT(len <= 2); // The maximum length of the BigInt data is less or equal 2
6004514f5e3Sopenharmony_ci    uint32_t lowBits = GetDigit(0);
6014514f5e3Sopenharmony_ci    uint32_t highBits = 0;
6024514f5e3Sopenharmony_ci    if (len > 1) {
6034514f5e3Sopenharmony_ci        highBits = GetDigit(1);
6044514f5e3Sopenharmony_ci    }
6054514f5e3Sopenharmony_ci    uint64_t value = static_cast<uint64_t>(lowBits);
6064514f5e3Sopenharmony_ci    value |= static_cast<uint64_t>(highBits) << DATEBITS;
6074514f5e3Sopenharmony_ci    if (GetSign()) {
6084514f5e3Sopenharmony_ci        value = ~(value - 1);
6094514f5e3Sopenharmony_ci    }
6104514f5e3Sopenharmony_ci    return value;
6114514f5e3Sopenharmony_ci}
6124514f5e3Sopenharmony_ci
6134514f5e3Sopenharmony_ciint64_t BigInt::ToInt64()
6144514f5e3Sopenharmony_ci{
6154514f5e3Sopenharmony_ci    return static_cast<int64_t>(ToUint64());
6164514f5e3Sopenharmony_ci}
6174514f5e3Sopenharmony_ci
6184514f5e3Sopenharmony_civoid BigInt::BigIntToInt64(JSThread *thread, JSHandle<JSTaggedValue> bigint, int64_t *cValue, bool *lossless)
6194514f5e3Sopenharmony_ci{
6204514f5e3Sopenharmony_ci    ASSERT(cValue != nullptr);
6214514f5e3Sopenharmony_ci    ASSERT(lossless != nullptr);
6224514f5e3Sopenharmony_ci    if (bigint->IsBoolean()) {
6234514f5e3Sopenharmony_ci        bigint = JSHandle<JSTaggedValue>(thread, JSTaggedValue::ToBigInt(thread, bigint));
6244514f5e3Sopenharmony_ci        RETURN_IF_ABRUPT_COMPLETION(thread);
6254514f5e3Sopenharmony_ci    } else if (!bigint->IsBigInt()) {
6264514f5e3Sopenharmony_ci        JSHandle<BigInt> bigInt64(thread, JSTaggedValue::ToBigInt64(thread, bigint));
6274514f5e3Sopenharmony_ci        RETURN_IF_ABRUPT_COMPLETION(thread);
6284514f5e3Sopenharmony_ci        *cValue = bigInt64->ToInt64();
6294514f5e3Sopenharmony_ci        return;
6304514f5e3Sopenharmony_ci    }
6314514f5e3Sopenharmony_ci    JSHandle<BigInt> bigInt64(thread, JSTaggedValue::ToBigInt64(thread, bigint));
6324514f5e3Sopenharmony_ci    RETURN_IF_ABRUPT_COMPLETION(thread);
6334514f5e3Sopenharmony_ci    if (Equal(bigInt64.GetTaggedValue(), bigint.GetTaggedValue())) {
6344514f5e3Sopenharmony_ci        *lossless = true;
6354514f5e3Sopenharmony_ci    } else {
6364514f5e3Sopenharmony_ci        *lossless = false;
6374514f5e3Sopenharmony_ci    }
6384514f5e3Sopenharmony_ci    *cValue = bigInt64->ToInt64();
6394514f5e3Sopenharmony_ci}
6404514f5e3Sopenharmony_ci
6414514f5e3Sopenharmony_civoid BigInt::BigIntToUint64(JSThread *thread, JSHandle<JSTaggedValue> bigint, uint64_t *cValue, bool *lossless)
6424514f5e3Sopenharmony_ci{
6434514f5e3Sopenharmony_ci    ASSERT(cValue != nullptr);
6444514f5e3Sopenharmony_ci    ASSERT(lossless != nullptr);
6454514f5e3Sopenharmony_ci    if (bigint->IsBoolean()) {
6464514f5e3Sopenharmony_ci        bigint = JSHandle<JSTaggedValue>(thread, JSTaggedValue::ToBigInt(thread, bigint));
6474514f5e3Sopenharmony_ci        RETURN_IF_ABRUPT_COMPLETION(thread);
6484514f5e3Sopenharmony_ci    } else if (!bigint->IsBigInt()) {
6494514f5e3Sopenharmony_ci        JSHandle<BigInt> bigInt64(thread, JSTaggedValue::ToBigUint64(thread, bigint));
6504514f5e3Sopenharmony_ci        RETURN_IF_ABRUPT_COMPLETION(thread);
6514514f5e3Sopenharmony_ci        *cValue = bigInt64->ToInt64();
6524514f5e3Sopenharmony_ci        return;
6534514f5e3Sopenharmony_ci    }
6544514f5e3Sopenharmony_ci    JSHandle<BigInt> bigUint64(thread, JSTaggedValue::ToBigUint64(thread, bigint));
6554514f5e3Sopenharmony_ci    RETURN_IF_ABRUPT_COMPLETION(thread);
6564514f5e3Sopenharmony_ci    if (Equal(bigUint64.GetTaggedValue(), bigint.GetTaggedValue())) {
6574514f5e3Sopenharmony_ci        *lossless = true;
6584514f5e3Sopenharmony_ci    } else {
6594514f5e3Sopenharmony_ci        *lossless = false;
6604514f5e3Sopenharmony_ci    }
6614514f5e3Sopenharmony_ci    *cValue = bigUint64->ToUint64();
6624514f5e3Sopenharmony_ci}
6634514f5e3Sopenharmony_ci
6644514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::CreateBigWords(JSThread *thread, bool sign, uint32_t size, const uint64_t *words)
6654514f5e3Sopenharmony_ci{
6664514f5e3Sopenharmony_ci    ASSERT(words != nullptr);
6674514f5e3Sopenharmony_ci    if (size == 0) {
6684514f5e3Sopenharmony_ci        return Uint64ToBigInt(thread, 0);
6694514f5e3Sopenharmony_ci    }
6704514f5e3Sopenharmony_ci    const uint32_t MULTIPLE = 2;
6714514f5e3Sopenharmony_ci    uint32_t needLen = size * MULTIPLE;
6724514f5e3Sopenharmony_ci    if (needLen > MAXSIZE) {
6734514f5e3Sopenharmony_ci        JSHandle<BigInt> bigint(thread, JSTaggedValue::Exception());
6744514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "Maximum BigInt size exceeded", bigint);
6754514f5e3Sopenharmony_ci    }
6764514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = CreateBigint(thread, needLen);
6774514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
6784514f5e3Sopenharmony_ci    for (uint32_t index = 0; index < size; ++index) {
6794514f5e3Sopenharmony_ci        uint32_t lowBits = static_cast<uint32_t>(words[index] & 0xffffffff);
6804514f5e3Sopenharmony_ci        uint32_t highBits = static_cast<uint32_t>((words[index] >> DATEBITS) & 0xffffffff);
6814514f5e3Sopenharmony_ci        bigint->SetDigit(MULTIPLE * index, lowBits);
6824514f5e3Sopenharmony_ci        bigint->SetDigit(MULTIPLE * index + 1, highBits);
6834514f5e3Sopenharmony_ci    }
6844514f5e3Sopenharmony_ci    bigint->SetSign(sign);
6854514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, bigint);
6864514f5e3Sopenharmony_ci}
6874514f5e3Sopenharmony_ci
6884514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::Add(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
6894514f5e3Sopenharmony_ci{
6904514f5e3Sopenharmony_ci    bool xSignFlag = x->GetSign();
6914514f5e3Sopenharmony_ci    bool ySignFlag = y->GetSign();
6924514f5e3Sopenharmony_ci    // x + y == x + y
6934514f5e3Sopenharmony_ci    // -x + -y == -(x + y)
6944514f5e3Sopenharmony_ci    if (xSignFlag == ySignFlag) {
6954514f5e3Sopenharmony_ci        return BigintAdd(thread, x, y, xSignFlag);
6964514f5e3Sopenharmony_ci    }
6974514f5e3Sopenharmony_ci    // x + -y == x - y == -(y - x)
6984514f5e3Sopenharmony_ci    // -x + y == y - x == -(x - y)
6994514f5e3Sopenharmony_ci    uint32_t xLength = x->GetLength();
7004514f5e3Sopenharmony_ci    uint32_t yLength = y->GetLength();
7014514f5e3Sopenharmony_ci    int i = static_cast<int>(xLength) - 1;
7024514f5e3Sopenharmony_ci    int subSize = static_cast<int>(xLength - yLength);
7034514f5e3Sopenharmony_ci    if (subSize > 0) {
7044514f5e3Sopenharmony_ci        return BigintSub(thread, x, y, xSignFlag);
7054514f5e3Sopenharmony_ci    } else if (subSize == 0) {
7064514f5e3Sopenharmony_ci        while (i > 0 && x->GetDigit(i) == y->GetDigit(i)) {
7074514f5e3Sopenharmony_ci            i--;
7084514f5e3Sopenharmony_ci        }
7094514f5e3Sopenharmony_ci        if ((x->GetDigit(i) > y->GetDigit(i))) {
7104514f5e3Sopenharmony_ci            return BigintSub(thread, x, y, xSignFlag);
7114514f5e3Sopenharmony_ci        } else {
7124514f5e3Sopenharmony_ci            return BigintSub(thread, y, x, ySignFlag);
7134514f5e3Sopenharmony_ci        }
7144514f5e3Sopenharmony_ci    } else {
7154514f5e3Sopenharmony_ci        return BigintSub(thread, y, x, ySignFlag);
7164514f5e3Sopenharmony_ci    }
7174514f5e3Sopenharmony_ci}
7184514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::Subtract(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
7194514f5e3Sopenharmony_ci{
7204514f5e3Sopenharmony_ci    bool xSignFlag = x->GetSign();
7214514f5e3Sopenharmony_ci    bool ySignFlag = y->GetSign();
7224514f5e3Sopenharmony_ci    if (xSignFlag != ySignFlag) {
7234514f5e3Sopenharmony_ci        // x - (-y) == x + y
7244514f5e3Sopenharmony_ci        // (-x) - y == -(x + y)
7254514f5e3Sopenharmony_ci        return BigintAdd(thread, x, y, xSignFlag);
7264514f5e3Sopenharmony_ci    }
7274514f5e3Sopenharmony_ci    // x - y == -(y - x)
7284514f5e3Sopenharmony_ci    // (-x) - (-y) == y - x == -(x - y)
7294514f5e3Sopenharmony_ci    uint32_t xLength = x->GetLength();
7304514f5e3Sopenharmony_ci    uint32_t yLength = y->GetLength();
7314514f5e3Sopenharmony_ci    ASSERT(xLength > 0);
7324514f5e3Sopenharmony_ci    uint32_t i = xLength - 1;
7334514f5e3Sopenharmony_ci    int subSize = static_cast<int>(xLength - yLength);
7344514f5e3Sopenharmony_ci    if (subSize > 0) {
7354514f5e3Sopenharmony_ci        return BigintSub(thread, x, y, xSignFlag);
7364514f5e3Sopenharmony_ci    } else if (subSize == 0) {
7374514f5e3Sopenharmony_ci        while (i > 0 && x->GetDigit(i) == y->GetDigit(i)) {
7384514f5e3Sopenharmony_ci            i--;
7394514f5e3Sopenharmony_ci        }
7404514f5e3Sopenharmony_ci        if ((x->GetDigit(i) > y->GetDigit(i))) {
7414514f5e3Sopenharmony_ci            return BigintSub(thread, x, y, xSignFlag);
7424514f5e3Sopenharmony_ci        } else {
7434514f5e3Sopenharmony_ci            return BigintSub(thread, y, x, !ySignFlag);
7444514f5e3Sopenharmony_ci        }
7454514f5e3Sopenharmony_ci    } else {
7464514f5e3Sopenharmony_ci        return BigintSub(thread, y, x, !ySignFlag);
7474514f5e3Sopenharmony_ci    }
7484514f5e3Sopenharmony_ci}
7494514f5e3Sopenharmony_ci
7504514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::BigintAdd(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y, bool resultSign)
7514514f5e3Sopenharmony_ci{
7524514f5e3Sopenharmony_ci    if (x->GetLength() < y->GetLength()) {
7534514f5e3Sopenharmony_ci        return BigintAdd(thread, y, x, resultSign);
7544514f5e3Sopenharmony_ci    }
7554514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = BigInt::CreateBigint(thread, x->GetLength() + 1);
7564514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
7574514f5e3Sopenharmony_ci    uint32_t bigintCarry = 0;
7584514f5e3Sopenharmony_ci    uint32_t i = 0;
7594514f5e3Sopenharmony_ci    while (i < y->GetLength()) {
7604514f5e3Sopenharmony_ci        uint32_t newBigintCarry = 0;
7614514f5e3Sopenharmony_ci        uint32_t addPlus = BigIntHelper::AddHelper(x->GetDigit(i), y->GetDigit(i), newBigintCarry);
7624514f5e3Sopenharmony_ci        addPlus = BigIntHelper::AddHelper(addPlus, bigintCarry, newBigintCarry);
7634514f5e3Sopenharmony_ci        bigint->SetDigit(i, addPlus);
7644514f5e3Sopenharmony_ci        bigintCarry = newBigintCarry;
7654514f5e3Sopenharmony_ci        i++;
7664514f5e3Sopenharmony_ci    }
7674514f5e3Sopenharmony_ci    while (i < x->GetLength()) {
7684514f5e3Sopenharmony_ci        uint32_t newBigintCarry = 0;
7694514f5e3Sopenharmony_ci        uint32_t addPlus = BigIntHelper::AddHelper(x->GetDigit(i), bigintCarry, newBigintCarry);
7704514f5e3Sopenharmony_ci        bigint->SetDigit(i, addPlus);
7714514f5e3Sopenharmony_ci        bigintCarry = newBigintCarry;
7724514f5e3Sopenharmony_ci        i++;
7734514f5e3Sopenharmony_ci    }
7744514f5e3Sopenharmony_ci    bigint->SetDigit(i, bigintCarry);
7754514f5e3Sopenharmony_ci    bigint->SetSign(resultSign);
7764514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, bigint);
7774514f5e3Sopenharmony_ci}
7784514f5e3Sopenharmony_ci
7794514f5e3Sopenharmony_ciinline uint32_t BigIntHelper::AddHelper(uint32_t x, uint32_t y, uint32_t &bigintCarry)
7804514f5e3Sopenharmony_ci{
7814514f5e3Sopenharmony_ci    uint32_t addPlus = x + y;
7824514f5e3Sopenharmony_ci    if (addPlus < x) {
7834514f5e3Sopenharmony_ci        bigintCarry += 1;
7844514f5e3Sopenharmony_ci    }
7854514f5e3Sopenharmony_ci    return addPlus;
7864514f5e3Sopenharmony_ci}
7874514f5e3Sopenharmony_ci
7884514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::BigintSub(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y, bool resultSign)
7894514f5e3Sopenharmony_ci{
7904514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = BigInt::CreateBigint(thread, x->GetLength());
7914514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
7924514f5e3Sopenharmony_ci    uint32_t bigintCarry = 0;
7934514f5e3Sopenharmony_ci    uint32_t i = 0;
7944514f5e3Sopenharmony_ci    while (i < y->GetLength()) {
7954514f5e3Sopenharmony_ci        uint32_t newBigintCarry = 0;
7964514f5e3Sopenharmony_ci        uint32_t minuSub = BigIntHelper::SubHelper(x->GetDigit(i), y->GetDigit(i), newBigintCarry);
7974514f5e3Sopenharmony_ci        minuSub = BigIntHelper::SubHelper(minuSub, bigintCarry, newBigintCarry);
7984514f5e3Sopenharmony_ci        bigint->SetDigit(i, minuSub);
7994514f5e3Sopenharmony_ci        bigintCarry = newBigintCarry;
8004514f5e3Sopenharmony_ci        i++;
8014514f5e3Sopenharmony_ci    }
8024514f5e3Sopenharmony_ci    while (i < x->GetLength()) {
8034514f5e3Sopenharmony_ci        uint32_t newBigintCarry = 0;
8044514f5e3Sopenharmony_ci        uint32_t minuSub = BigIntHelper::SubHelper(x->GetDigit(i), bigintCarry, newBigintCarry);
8054514f5e3Sopenharmony_ci        bigint->SetDigit(i, minuSub);
8064514f5e3Sopenharmony_ci        bigintCarry = newBigintCarry;
8074514f5e3Sopenharmony_ci        i++;
8084514f5e3Sopenharmony_ci    }
8094514f5e3Sopenharmony_ci    bigint->SetSign(resultSign);
8104514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, bigint);
8114514f5e3Sopenharmony_ci}
8124514f5e3Sopenharmony_ci
8134514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::BigintAddOne(JSThread *thread, JSHandle<BigInt> x)
8144514f5e3Sopenharmony_ci{
8154514f5e3Sopenharmony_ci    JSHandle<BigInt> temp = Int32ToBigInt(thread, 1);
8164514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
8174514f5e3Sopenharmony_ci    return Add(thread, x, temp);
8184514f5e3Sopenharmony_ci}
8194514f5e3Sopenharmony_ci
8204514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::BigintSubOne(JSThread *thread, JSHandle<BigInt> x)
8214514f5e3Sopenharmony_ci{
8224514f5e3Sopenharmony_ci    JSHandle<BigInt> temp = Int32ToBigInt(thread, 1);
8234514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
8244514f5e3Sopenharmony_ci    return Subtract(thread, x, temp);
8254514f5e3Sopenharmony_ci}
8264514f5e3Sopenharmony_ci
8274514f5e3Sopenharmony_ciinline uint32_t BigIntHelper::SubHelper(uint32_t x, uint32_t y, uint32_t &bigintCarry)
8284514f5e3Sopenharmony_ci{
8294514f5e3Sopenharmony_ci    ASSERT(x - y >= 0);
8304514f5e3Sopenharmony_ci    uint32_t minuSub = x - y;
8314514f5e3Sopenharmony_ci    if (minuSub > x) {
8324514f5e3Sopenharmony_ci        bigintCarry += 1;
8334514f5e3Sopenharmony_ci    }
8344514f5e3Sopenharmony_ci    return minuSub;
8354514f5e3Sopenharmony_ci}
8364514f5e3Sopenharmony_ci
8374514f5e3Sopenharmony_ciComparisonResult BigInt::Compare(const JSTaggedValue &x, const JSTaggedValue &y)
8384514f5e3Sopenharmony_ci{
8394514f5e3Sopenharmony_ci    BigInt* xVal = BigInt::Cast(x.GetTaggedObject());
8404514f5e3Sopenharmony_ci    BigInt* yVal = BigInt::Cast(y.GetTaggedObject());
8414514f5e3Sopenharmony_ci    return Compare(xVal, yVal);
8424514f5e3Sopenharmony_ci}
8434514f5e3Sopenharmony_ci
8444514f5e3Sopenharmony_ciComparisonResult BigInt::Compare(const BigInt *x, const BigInt *y)
8454514f5e3Sopenharmony_ci{
8464514f5e3Sopenharmony_ci    bool xSign = x->GetSign();
8474514f5e3Sopenharmony_ci    bool ySign = y->GetSign();
8484514f5e3Sopenharmony_ci    if (xSign != ySign) {
8494514f5e3Sopenharmony_ci        return xSign ? ComparisonResult::LESS : ComparisonResult::GREAT;
8504514f5e3Sopenharmony_ci    }
8514514f5e3Sopenharmony_ci    ComparisonResult compar = AbsolutelyCompare(x, y);
8524514f5e3Sopenharmony_ci    if (xSign && compar != ComparisonResult::EQUAL) {
8534514f5e3Sopenharmony_ci        return compar == ComparisonResult::LESS ? ComparisonResult::GREAT : ComparisonResult::LESS;
8544514f5e3Sopenharmony_ci    }
8554514f5e3Sopenharmony_ci    return compar;
8564514f5e3Sopenharmony_ci}
8574514f5e3Sopenharmony_ci
8584514f5e3Sopenharmony_cibool BigInt::LessThan(const JSTaggedValue &x, const JSTaggedValue &y)
8594514f5e3Sopenharmony_ci{
8604514f5e3Sopenharmony_ci    return Compare(x, y) == ComparisonResult::LESS;
8614514f5e3Sopenharmony_ci}
8624514f5e3Sopenharmony_ci
8634514f5e3Sopenharmony_cibool BigInt::LessThan(const BigInt *x, const BigInt *y)
8644514f5e3Sopenharmony_ci{
8654514f5e3Sopenharmony_ci    ASSERT(x != nullptr);
8664514f5e3Sopenharmony_ci    ASSERT(y != nullptr);
8674514f5e3Sopenharmony_ci    return Compare(x, y) == ComparisonResult::LESS;
8684514f5e3Sopenharmony_ci}
8694514f5e3Sopenharmony_ci
8704514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::SignedRightShift(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
8714514f5e3Sopenharmony_ci{
8724514f5e3Sopenharmony_ci    if (x->IsZero() || y->IsZero()) {
8734514f5e3Sopenharmony_ci        return x;
8744514f5e3Sopenharmony_ci    }
8754514f5e3Sopenharmony_ci    if (y->GetSign()) {
8764514f5e3Sopenharmony_ci        return LeftShiftHelper(thread, x, y);
8774514f5e3Sopenharmony_ci    } else {
8784514f5e3Sopenharmony_ci        return RightShiftHelper(thread, x, y);
8794514f5e3Sopenharmony_ci    }
8804514f5e3Sopenharmony_ci}
8814514f5e3Sopenharmony_ci
8824514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::ReturnIfRightShiftOverMax(JSThread *thread, bool sign)
8834514f5e3Sopenharmony_ci{
8844514f5e3Sopenharmony_ci    if (sign) {
8854514f5e3Sopenharmony_ci        return Int32ToBigInt(thread, -1);
8864514f5e3Sopenharmony_ci    }
8874514f5e3Sopenharmony_ci    return Int32ToBigInt(thread, 0);
8884514f5e3Sopenharmony_ci}
8894514f5e3Sopenharmony_ci
8904514f5e3Sopenharmony_civoid BigInt::RightShift(JSHandle<BigInt> bigint, JSHandle<BigInt> x, uint32_t digitMove, uint32_t bitsMove)
8914514f5e3Sopenharmony_ci{
8924514f5e3Sopenharmony_ci    uint32_t size = x->GetLength();
8934514f5e3Sopenharmony_ci    if (bitsMove == 0) {
8944514f5e3Sopenharmony_ci        for (uint32_t i = digitMove; i < size; i++) {
8954514f5e3Sopenharmony_ci            bigint->SetDigit(i - digitMove, x->GetDigit(i));
8964514f5e3Sopenharmony_ci        }
8974514f5e3Sopenharmony_ci    } else {
8984514f5e3Sopenharmony_ci        uint32_t carry = x->GetDigit(digitMove) >> bitsMove;
8994514f5e3Sopenharmony_ci        ASSERT(size > digitMove);
9004514f5e3Sopenharmony_ci        uint32_t last = size - digitMove - 1;
9014514f5e3Sopenharmony_ci        for (uint32_t i = 0; i < last; i++) {
9024514f5e3Sopenharmony_ci            uint32_t value = x->GetDigit(i + digitMove + 1);
9034514f5e3Sopenharmony_ci            bigint->SetDigit(i, (value << (DATEBITS - bitsMove)) | carry);
9044514f5e3Sopenharmony_ci            carry = value >> bitsMove;
9054514f5e3Sopenharmony_ci        }
9064514f5e3Sopenharmony_ci        bigint->SetDigit(last, carry);
9074514f5e3Sopenharmony_ci    }
9084514f5e3Sopenharmony_ci}
9094514f5e3Sopenharmony_ci
9104514f5e3Sopenharmony_civoid BigInt::JudgeRoundDown(JSHandle<BigInt> x, uint32_t digitMove, uint32_t bitsMove, uint32_t &needLen,
9114514f5e3Sopenharmony_ci                            bool &roundDown)
9124514f5e3Sopenharmony_ci{
9134514f5e3Sopenharmony_ci    uint32_t stamp = (static_cast<uint32_t>(1U) << bitsMove) - 1;
9144514f5e3Sopenharmony_ci    if (x->GetDigit(digitMove) & stamp) {
9154514f5e3Sopenharmony_ci        roundDown = true;
9164514f5e3Sopenharmony_ci    } else {
9174514f5e3Sopenharmony_ci        for (uint32_t i = 0; i < digitMove; i++) {
9184514f5e3Sopenharmony_ci            if (x->GetDigit(i) != 0) {
9194514f5e3Sopenharmony_ci                roundDown = true;
9204514f5e3Sopenharmony_ci                break;
9214514f5e3Sopenharmony_ci            }
9224514f5e3Sopenharmony_ci        }
9234514f5e3Sopenharmony_ci    }
9244514f5e3Sopenharmony_ci
9254514f5e3Sopenharmony_ci    if (roundDown && bitsMove == 0) {
9264514f5e3Sopenharmony_ci        ASSERT(x->GetLength() > 0);
9274514f5e3Sopenharmony_ci        uint32_t highBits = x->GetDigit(x->GetLength() - 1);
9284514f5e3Sopenharmony_ci        // If all the most significant bits are 1, we think that carry will cause overflow,
9294514f5e3Sopenharmony_ci        // and needLen needs to be increased by 1
9304514f5e3Sopenharmony_ci        if ((~highBits) == 0) {
9314514f5e3Sopenharmony_ci            needLen++;
9324514f5e3Sopenharmony_ci        }
9334514f5e3Sopenharmony_ci    }
9344514f5e3Sopenharmony_ci}
9354514f5e3Sopenharmony_ci
9364514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::RightShiftHelper(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
9374514f5e3Sopenharmony_ci{
9384514f5e3Sopenharmony_ci    bool sign = x->GetSign();
9394514f5e3Sopenharmony_ci    if (y->GetLength() > 1 || y->GetDigit(0) > MAXBITS) {
9404514f5e3Sopenharmony_ci        return ReturnIfRightShiftOverMax(thread, sign);
9414514f5e3Sopenharmony_ci    }
9424514f5e3Sopenharmony_ci    uint32_t moveNum = y->GetDigit(0);
9434514f5e3Sopenharmony_ci    uint32_t digitMove = moveNum / DATEBITS;
9444514f5e3Sopenharmony_ci    uint32_t bitsMove = moveNum % DATEBITS;
9454514f5e3Sopenharmony_ci    if (x->GetLength() <= digitMove) {
9464514f5e3Sopenharmony_ci        return ReturnIfRightShiftOverMax(thread, sign);
9474514f5e3Sopenharmony_ci    }
9484514f5e3Sopenharmony_ci    uint32_t needLen = x->GetLength() - digitMove;
9494514f5e3Sopenharmony_ci    bool roundDown = false;
9504514f5e3Sopenharmony_ci    if (sign) {
9514514f5e3Sopenharmony_ci        // If it is a negative number, you need to consider whether it will carry after moving.
9524514f5e3Sopenharmony_ci        // NeedLen may need to increase by 1
9534514f5e3Sopenharmony_ci        JudgeRoundDown(x, digitMove, bitsMove, needLen, roundDown);
9544514f5e3Sopenharmony_ci    }
9554514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = CreateBigint(thread, needLen);
9564514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
9574514f5e3Sopenharmony_ci
9584514f5e3Sopenharmony_ci    RightShift(bigint, x, digitMove, bitsMove);
9594514f5e3Sopenharmony_ci    bigint = BigIntHelper::RightTruncate(thread, bigint);
9604514f5e3Sopenharmony_ci    if (sign) {
9614514f5e3Sopenharmony_ci        bigint->SetSign(true);
9624514f5e3Sopenharmony_ci        if (roundDown) {
9634514f5e3Sopenharmony_ci            return BitwiseAddOne(thread, bigint);
9644514f5e3Sopenharmony_ci        }
9654514f5e3Sopenharmony_ci    }
9664514f5e3Sopenharmony_ci    return bigint;
9674514f5e3Sopenharmony_ci}
9684514f5e3Sopenharmony_ci
9694514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::LeftShift(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
9704514f5e3Sopenharmony_ci{
9714514f5e3Sopenharmony_ci    if (y->GetSign()) {
9724514f5e3Sopenharmony_ci        return RightShiftHelper(thread, x, y);
9734514f5e3Sopenharmony_ci    } else {
9744514f5e3Sopenharmony_ci        return LeftShiftHelper(thread, x, y);
9754514f5e3Sopenharmony_ci    }
9764514f5e3Sopenharmony_ci}
9774514f5e3Sopenharmony_ci
9784514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::LeftShiftHelper(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
9794514f5e3Sopenharmony_ci{
9804514f5e3Sopenharmony_ci    if (x->IsZero()) {
9814514f5e3Sopenharmony_ci        return x;
9824514f5e3Sopenharmony_ci    }
9834514f5e3Sopenharmony_ci    ASSERT(y->GetLength() > 0);
9844514f5e3Sopenharmony_ci    uint32_t moveNum = y->GetDigit(0);
9854514f5e3Sopenharmony_ci    uint32_t digitMove = moveNum / DATEBITS;
9864514f5e3Sopenharmony_ci    uint32_t bitsMove = moveNum % DATEBITS;
9874514f5e3Sopenharmony_ci    // If bitsMove is not zero, needLen needs to be increased by 1
9884514f5e3Sopenharmony_ci    uint32_t needLen = digitMove + x->GetLength() + static_cast<uint32_t>(!!bitsMove);
9894514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = CreateBigint(thread, needLen);
9904514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
9914514f5e3Sopenharmony_ci    if (bitsMove == 0) {
9924514f5e3Sopenharmony_ci        uint32_t index = digitMove;
9934514f5e3Sopenharmony_ci        while (index < needLen) {
9944514f5e3Sopenharmony_ci            bigint->SetDigit(index, x->GetDigit(index - digitMove));
9954514f5e3Sopenharmony_ci            ++index;
9964514f5e3Sopenharmony_ci        }
9974514f5e3Sopenharmony_ci    } else {
9984514f5e3Sopenharmony_ci        uint32_t carry = 0;
9994514f5e3Sopenharmony_ci        uint32_t index = 0;
10004514f5e3Sopenharmony_ci        while (index < x->GetLength()) {
10014514f5e3Sopenharmony_ci            uint32_t value = x->GetDigit(index);
10024514f5e3Sopenharmony_ci            bigint->SetDigit(index + digitMove, (value << bitsMove) | carry);
10034514f5e3Sopenharmony_ci            carry = value >> (DATEBITS - bitsMove);
10044514f5e3Sopenharmony_ci            ++index;
10054514f5e3Sopenharmony_ci        }
10064514f5e3Sopenharmony_ci        if (carry != 0) {
10074514f5e3Sopenharmony_ci            ASSERT(index + digitMove < needLen);
10084514f5e3Sopenharmony_ci            bigint->SetDigit(index + digitMove, carry);
10094514f5e3Sopenharmony_ci        }
10104514f5e3Sopenharmony_ci    }
10114514f5e3Sopenharmony_ci    bigint->SetSign(x->GetSign());
10124514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, bigint);
10134514f5e3Sopenharmony_ci}
10144514f5e3Sopenharmony_ci
10154514f5e3Sopenharmony_ciJSTaggedValue BigInt::UnsignedRightShift(JSThread *thread)
10164514f5e3Sopenharmony_ci{
10174514f5e3Sopenharmony_ci    THROW_TYPE_ERROR_AND_RETURN(thread, "BigInt have no unsigned right shift, use >> instead",
10184514f5e3Sopenharmony_ci                                JSTaggedValue::Exception());
10194514f5e3Sopenharmony_ci}
10204514f5e3Sopenharmony_ci
10214514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::Copy(JSThread *thread, JSHandle<BigInt> x, uint32_t len)
10224514f5e3Sopenharmony_ci{
10234514f5e3Sopenharmony_ci    ASSERT(x->GetLength() >= len);
10244514f5e3Sopenharmony_ci    JSHandle<BigInt> newBig = CreateBigint(thread, len);
10254514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
10264514f5e3Sopenharmony_ci    std::copy(x->GetData(), x->GetData() + len, newBig->GetData());
10274514f5e3Sopenharmony_ci    newBig->SetSign(x->GetSign());
10284514f5e3Sopenharmony_ci    return newBig;
10294514f5e3Sopenharmony_ci}
10304514f5e3Sopenharmony_ci
10314514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::UnaryMinus(JSThread *thread, JSHandle<BigInt> x)
10324514f5e3Sopenharmony_ci{
10334514f5e3Sopenharmony_ci    if (x->IsZero()) {
10344514f5e3Sopenharmony_ci        return x;
10354514f5e3Sopenharmony_ci    }
10364514f5e3Sopenharmony_ci    JSHandle<BigInt> y = Copy(thread, x, x->GetLength());
10374514f5e3Sopenharmony_ci    y->SetSign(!y->GetSign());
10384514f5e3Sopenharmony_ci    return y;
10394514f5e3Sopenharmony_ci}
10404514f5e3Sopenharmony_ci
10414514f5e3Sopenharmony_ci// 6.1.6.2.2   BigInt::bitwiseNOT ( x )
10424514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::BitwiseNOT(JSThread *thread, JSHandle<BigInt> x)
10434514f5e3Sopenharmony_ci{
10444514f5e3Sopenharmony_ci    // ~(-x) == ~(~(x-1)) == x-1
10454514f5e3Sopenharmony_ci    // ~x == -x-1 == -(x+1)
10464514f5e3Sopenharmony_ci    JSHandle<BigInt> result = BigintAddOne(thread, x);
10474514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
10484514f5e3Sopenharmony_ci    if (x->GetSign()) {
10494514f5e3Sopenharmony_ci        result->SetSign(false);
10504514f5e3Sopenharmony_ci    } else {
10514514f5e3Sopenharmony_ci        result->SetSign(true);
10524514f5e3Sopenharmony_ci    }
10534514f5e3Sopenharmony_ci    return result;
10544514f5e3Sopenharmony_ci}
10554514f5e3Sopenharmony_ci
10564514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::Exponentiate(JSThread *thread, JSHandle<BigInt> base, JSHandle<BigInt> exponent)
10574514f5e3Sopenharmony_ci{
10584514f5e3Sopenharmony_ci    if (exponent->GetSign()) {
10594514f5e3Sopenharmony_ci        JSHandle<BigInt> bigint(thread, JSTaggedValue::Exception());
10604514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "Exponent must be positive", bigint);
10614514f5e3Sopenharmony_ci    }
10624514f5e3Sopenharmony_ci    ASSERT(exponent->GetLength() > 0);
10634514f5e3Sopenharmony_ci    if (exponent->IsZero()) {
10644514f5e3Sopenharmony_ci        return Int32ToBigInt(thread, 1);
10654514f5e3Sopenharmony_ci    }
10664514f5e3Sopenharmony_ci    if (base->IsZero()) {
10674514f5e3Sopenharmony_ci        return base;
10684514f5e3Sopenharmony_ci    }
10694514f5e3Sopenharmony_ci    uint32_t expValue = exponent->GetDigit(0);
10704514f5e3Sopenharmony_ci    if (base->GetLength() == 1 && base->GetDigit(0) == 1) {
10714514f5e3Sopenharmony_ci        if (base->GetSign() && !(expValue & 1)) {
10724514f5e3Sopenharmony_ci            return BigInt::UnaryMinus(thread, base);
10734514f5e3Sopenharmony_ci        }
10744514f5e3Sopenharmony_ci        return base;
10754514f5e3Sopenharmony_ci    }
10764514f5e3Sopenharmony_ci    if (exponent->GetLength() > 1) {
10774514f5e3Sopenharmony_ci        // The result is at least 2n ** 2n ** 32n, which is too big.
10784514f5e3Sopenharmony_ci        JSHandle<BigInt> bigint(thread, JSTaggedValue::Exception());
10794514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "Maximum BigInt size exceeded", bigint);
10804514f5e3Sopenharmony_ci    }
10814514f5e3Sopenharmony_ci
10824514f5e3Sopenharmony_ci    if (base->GetLength() == 1 && base->GetDigit(0) == 2) { // 2 : We use fast path processing 2 ^ n
10834514f5e3Sopenharmony_ci        uint32_t needLength = expValue / DATEBITS + 1;
10844514f5e3Sopenharmony_ci        JSHandle<BigInt> bigint = CreateBigint(thread, needLength);
10854514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
10864514f5e3Sopenharmony_ci        uint32_t value = 1U << (expValue % DATEBITS);
10874514f5e3Sopenharmony_ci        bigint->SetDigit(needLength - 1, value);
10884514f5e3Sopenharmony_ci        if (base->GetSign()) {
10894514f5e3Sopenharmony_ci            bigint->SetSign(static_cast<bool>(expValue & 1));
10904514f5e3Sopenharmony_ci        }
10914514f5e3Sopenharmony_ci        return bigint;
10924514f5e3Sopenharmony_ci    }
10934514f5e3Sopenharmony_ci    JSMutableHandle<BigInt> result(thread, JSTaggedValue::Null());
10944514f5e3Sopenharmony_ci    JSMutableHandle<BigInt> temp(thread, base);
10954514f5e3Sopenharmony_ci    if (expValue & 1) {
10964514f5e3Sopenharmony_ci        result.Update(base);
10974514f5e3Sopenharmony_ci    }
10984514f5e3Sopenharmony_ci    expValue >>= 1;
10994514f5e3Sopenharmony_ci    for (; expValue; expValue >>= 1) {
11004514f5e3Sopenharmony_ci        temp.Update(BigInt::Multiply(thread, temp, temp));
11014514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
11024514f5e3Sopenharmony_ci        if (expValue & 1) {
11034514f5e3Sopenharmony_ci            if (result.GetTaggedValue().IsNull()) {
11044514f5e3Sopenharmony_ci                result.Update(temp);
11054514f5e3Sopenharmony_ci            } else {
11064514f5e3Sopenharmony_ci                result.Update(BigInt::Multiply(thread, result, temp));
11074514f5e3Sopenharmony_ci                RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
11084514f5e3Sopenharmony_ci            }
11094514f5e3Sopenharmony_ci        }
11104514f5e3Sopenharmony_ci    }
11114514f5e3Sopenharmony_ci    ASSERT(result.GetTaggedValue().IsBigInt());
11124514f5e3Sopenharmony_ci    return result;
11134514f5e3Sopenharmony_ci}
11144514f5e3Sopenharmony_ci
11154514f5e3Sopenharmony_cistd::tuple<uint32_t, uint32_t> BigInt::Mul(uint32_t x, uint32_t y)
11164514f5e3Sopenharmony_ci{
11174514f5e3Sopenharmony_ci    uint32_t lowBitX = x & HALFDATEMASK;
11184514f5e3Sopenharmony_ci    uint32_t highBitX = x >> HALFDATEBITS;
11194514f5e3Sopenharmony_ci    uint32_t lowBitY = y & HALFDATEMASK;
11204514f5e3Sopenharmony_ci    uint32_t highBitY = y >> HALFDATEBITS;
11214514f5e3Sopenharmony_ci    // {highBitX lowBitX} * {highBitY lowBitY}
11224514f5e3Sopenharmony_ci    uint32_t lowRes = lowBitX * lowBitY;
11234514f5e3Sopenharmony_ci    uint32_t highRes = highBitX * highBitY;
11244514f5e3Sopenharmony_ci    uint32_t midRes1 = lowBitX * highBitY;
11254514f5e3Sopenharmony_ci    uint32_t midRes2 = highBitX * lowBitY;
11264514f5e3Sopenharmony_ci
11274514f5e3Sopenharmony_ci    uint32_t carry = 0;
11284514f5e3Sopenharmony_ci    uint32_t low = BigIntHelper::AddHelper(
11294514f5e3Sopenharmony_ci        BigIntHelper::AddHelper(lowRes, midRes1 << HALFDATEBITS, carry), midRes2 << HALFDATEBITS, carry);
11304514f5e3Sopenharmony_ci    uint32_t high = (midRes1 >> HALFDATEBITS) + (midRes2 >> HALFDATEBITS) + highRes + carry;
11314514f5e3Sopenharmony_ci
11324514f5e3Sopenharmony_ci    return std::make_tuple(high, low);
11334514f5e3Sopenharmony_ci}
11344514f5e3Sopenharmony_ci
11354514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::Multiply(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
11364514f5e3Sopenharmony_ci{
11374514f5e3Sopenharmony_ci    if (x->IsZero()) {
11384514f5e3Sopenharmony_ci        return x;
11394514f5e3Sopenharmony_ci    }
11404514f5e3Sopenharmony_ci    if (y->IsZero()) {
11414514f5e3Sopenharmony_ci        return y;
11424514f5e3Sopenharmony_ci    }
11434514f5e3Sopenharmony_ci    uint32_t needLength = x->GetLength() + y->GetLength();
11444514f5e3Sopenharmony_ci    JSHandle<BigInt> bigint = BigInt::CreateBigint(thread, needLength);
11454514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
11464514f5e3Sopenharmony_ci    // the algorithm here is similar to the way we use paper money to calculate multiplication.
11474514f5e3Sopenharmony_ci    // Generally, we first calculate the partial product, and then add up to get the result.
11484514f5e3Sopenharmony_ci    // The only difference here is that multiplication and addition are calculated synchronously
11494514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < x->GetLength(); i++) {
11504514f5e3Sopenharmony_ci        uint32_t xVal = x->GetDigit(i);
11514514f5e3Sopenharmony_ci        // If the current multiplier is 0, we will skip this round of calculation to improve performance.
11524514f5e3Sopenharmony_ci        // If we do not skip, the correctness of the calculation will not be affected
11534514f5e3Sopenharmony_ci        if (xVal == 0) {
11544514f5e3Sopenharmony_ci            continue;
11554514f5e3Sopenharmony_ci        }
11564514f5e3Sopenharmony_ci        uint32_t carry = 0;
11574514f5e3Sopenharmony_ci        uint32_t high = 0;
11584514f5e3Sopenharmony_ci        uint32_t index = i;
11594514f5e3Sopenharmony_ci        for (uint32_t j = 0; j < y->GetLength(); j++) {
11604514f5e3Sopenharmony_ci            uint32_t currentCarry = 0;
11614514f5e3Sopenharmony_ci            uint32_t value = bigint->GetDigit(index);
11624514f5e3Sopenharmony_ci            value = BigIntHelper::AddHelper(value, high, currentCarry);
11634514f5e3Sopenharmony_ci            value = BigIntHelper::AddHelper(value, carry, currentCarry);
11644514f5e3Sopenharmony_ci
11654514f5e3Sopenharmony_ci            uint32_t low;
11664514f5e3Sopenharmony_ci            std::tie(high, low) = Mul(xVal, y->GetDigit(j));
11674514f5e3Sopenharmony_ci            value = BigIntHelper::AddHelper(value, low, currentCarry);
11684514f5e3Sopenharmony_ci            bigint->SetDigit(index, value);
11694514f5e3Sopenharmony_ci            carry = currentCarry;
11704514f5e3Sopenharmony_ci            index++;
11714514f5e3Sopenharmony_ci        }
11724514f5e3Sopenharmony_ci        while (carry != 0 || high != 0) {
11734514f5e3Sopenharmony_ci            ASSERT(index < bigint->GetLength());
11744514f5e3Sopenharmony_ci            uint32_t value = bigint->GetDigit(index);
11754514f5e3Sopenharmony_ci            uint32_t currentCarry = 0;
11764514f5e3Sopenharmony_ci            value = BigIntHelper::AddHelper(value, high, currentCarry);
11774514f5e3Sopenharmony_ci            high = 0;
11784514f5e3Sopenharmony_ci            value = BigIntHelper::AddHelper(value, carry, currentCarry);
11794514f5e3Sopenharmony_ci            bigint->SetDigit(index, value);
11804514f5e3Sopenharmony_ci            carry = currentCarry;
11814514f5e3Sopenharmony_ci            index++;
11824514f5e3Sopenharmony_ci        }
11834514f5e3Sopenharmony_ci    }
11844514f5e3Sopenharmony_ci
11854514f5e3Sopenharmony_ci    bigint->SetSign(x->GetSign() != y->GetSign());
11864514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, bigint);
11874514f5e3Sopenharmony_ci}
11884514f5e3Sopenharmony_ci
11894514f5e3Sopenharmony_civoid BigIntHelper::DeZero(CString &a)
11904514f5e3Sopenharmony_ci{
11914514f5e3Sopenharmony_ci    size_t count = 0;
11924514f5e3Sopenharmony_ci    while (count < a.size() && a[count] == '0') {
11934514f5e3Sopenharmony_ci        count++;
11944514f5e3Sopenharmony_ci    }
11954514f5e3Sopenharmony_ci    if (count == a.size()) {
11964514f5e3Sopenharmony_ci        a = "0";
11974514f5e3Sopenharmony_ci    } else {
11984514f5e3Sopenharmony_ci        a = a.substr(count);
11994514f5e3Sopenharmony_ci    }
12004514f5e3Sopenharmony_ci}
12014514f5e3Sopenharmony_ci
12024514f5e3Sopenharmony_ciComparisonResult BigInt::AbsolutelyCompare(const BigInt *x, const BigInt *y)
12034514f5e3Sopenharmony_ci{
12044514f5e3Sopenharmony_ci    uint32_t xLen = x->GetLength();
12054514f5e3Sopenharmony_ci    uint32_t yLen = y->GetLength();
12064514f5e3Sopenharmony_ci    if (xLen > yLen) {
12074514f5e3Sopenharmony_ci        return ComparisonResult::GREAT;
12084514f5e3Sopenharmony_ci    } else if (xLen < yLen) {
12094514f5e3Sopenharmony_ci        return ComparisonResult::LESS;
12104514f5e3Sopenharmony_ci    } else {
12114514f5e3Sopenharmony_ci        int index = static_cast<int>(xLen) - 1;
12124514f5e3Sopenharmony_ci        for (; index >= 0; --index) {
12134514f5e3Sopenharmony_ci            if (x->GetDigit(index) != y->GetDigit(index)) {
12144514f5e3Sopenharmony_ci                break;
12154514f5e3Sopenharmony_ci            }
12164514f5e3Sopenharmony_ci        }
12174514f5e3Sopenharmony_ci        if (index < 0) {
12184514f5e3Sopenharmony_ci            return ComparisonResult::EQUAL;
12194514f5e3Sopenharmony_ci        }
12204514f5e3Sopenharmony_ci        return x->GetDigit(index) > y->GetDigit(index) ? ComparisonResult::GREAT : ComparisonResult::LESS;
12214514f5e3Sopenharmony_ci    }
12224514f5e3Sopenharmony_ci}
12234514f5e3Sopenharmony_ci
12244514f5e3Sopenharmony_ciuint32_t BigInt::DivideAndRemainder(uint32_t highBit, uint32_t lowBit, uint32_t divisor, uint32_t& remainder)
12254514f5e3Sopenharmony_ci{
12264514f5e3Sopenharmony_ci    uint32_t leadingZeros = base::CountLeadingZeros(divisor);
12274514f5e3Sopenharmony_ci    // Before calculating, we need to align the operands to the left
12284514f5e3Sopenharmony_ci    divisor <<= leadingZeros;
12294514f5e3Sopenharmony_ci    uint32_t lowDividend = lowBit << leadingZeros;
12304514f5e3Sopenharmony_ci    uint32_t highDividend = highBit;
12314514f5e3Sopenharmony_ci    if (leadingZeros != 0) {
12324514f5e3Sopenharmony_ci        // highBit is the remainder of the last calculation, which must be less than or equal to the divisor,
12334514f5e3Sopenharmony_ci        // so high << leadingZeros will not lose the significant bit
12344514f5e3Sopenharmony_ci        highDividend = (highBit << leadingZeros) | (lowBit >> (DATEBITS - leadingZeros));
12354514f5e3Sopenharmony_ci    }
12364514f5e3Sopenharmony_ci    uint32_t highDivisor = divisor >> HALFDATEBITS;
12374514f5e3Sopenharmony_ci    uint32_t lowDivisor = divisor & HALFDATEMASK;
12384514f5e3Sopenharmony_ci    uint32_t lowDividend1 = lowDividend >> HALFDATEBITS;
12394514f5e3Sopenharmony_ci    uint32_t lowDividend2 = lowDividend & HALFDATEMASK;
12404514f5e3Sopenharmony_ci    uint32_t highQuotient = highDividend / highDivisor;
12414514f5e3Sopenharmony_ci    uint32_t tempRemainder = highDividend - highQuotient * highDivisor;
12424514f5e3Sopenharmony_ci
12434514f5e3Sopenharmony_ci    // Similar to the ordinary division calculation, here we use HALFUINT32VALUE as the carry unit
12444514f5e3Sopenharmony_ci    // Calculate high order results first
12454514f5e3Sopenharmony_ci    while (highQuotient >= HALFUINT32VALUE ||
12464514f5e3Sopenharmony_ci           highQuotient * lowDivisor > tempRemainder * HALFUINT32VALUE + lowDividend1) {
12474514f5e3Sopenharmony_ci        highQuotient--;
12484514f5e3Sopenharmony_ci        tempRemainder += highDivisor;
12494514f5e3Sopenharmony_ci        if (tempRemainder >= HALFUINT32VALUE) {
12504514f5e3Sopenharmony_ci            break;
12514514f5e3Sopenharmony_ci        }
12524514f5e3Sopenharmony_ci    }
12534514f5e3Sopenharmony_ci    uint32_t tempLowDividend = highDividend * HALFUINT32VALUE + lowDividend1 - highQuotient * divisor;
12544514f5e3Sopenharmony_ci    uint32_t lowQuotient = tempLowDividend / highDivisor;
12554514f5e3Sopenharmony_ci    tempRemainder = tempLowDividend - lowQuotient * highDivisor;
12564514f5e3Sopenharmony_ci
12574514f5e3Sopenharmony_ci    // Then calculate the low order result
12584514f5e3Sopenharmony_ci    while (lowQuotient >= HALFUINT32VALUE ||
12594514f5e3Sopenharmony_ci           lowQuotient * lowDivisor > tempRemainder * HALFUINT32VALUE + lowDividend2) {
12604514f5e3Sopenharmony_ci        lowQuotient--;
12614514f5e3Sopenharmony_ci        tempRemainder += highDivisor;
12624514f5e3Sopenharmony_ci        if (tempRemainder >= HALFUINT32VALUE) {
12634514f5e3Sopenharmony_ci            break;
12644514f5e3Sopenharmony_ci        }
12654514f5e3Sopenharmony_ci    }
12664514f5e3Sopenharmony_ci
12674514f5e3Sopenharmony_ci    // In order to facilitate the calculation, we start to make left alignment
12684514f5e3Sopenharmony_ci    // At this time, we need to move right to get the correct remainder
12694514f5e3Sopenharmony_ci    remainder = (tempLowDividend * HALFUINT32VALUE + lowDividend2 - lowQuotient * divisor) >> leadingZeros;
12704514f5e3Sopenharmony_ci    return highQuotient * HALFUINT32VALUE + lowQuotient;
12714514f5e3Sopenharmony_ci}
12724514f5e3Sopenharmony_ci
12734514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::FormatLeftShift(JSThread *thread, uint32_t shift, JSHandle<BigInt> bigint, bool neeedAddOne)
12744514f5e3Sopenharmony_ci{
12754514f5e3Sopenharmony_ci    if (!neeedAddOne && shift == 0) {
12764514f5e3Sopenharmony_ci        return bigint;
12774514f5e3Sopenharmony_ci    }
12784514f5e3Sopenharmony_ci    uint32_t len = bigint->GetLength();
12794514f5e3Sopenharmony_ci    uint32_t needLen = len;
12804514f5e3Sopenharmony_ci    if (neeedAddOne) {
12814514f5e3Sopenharmony_ci        needLen += 1;
12824514f5e3Sopenharmony_ci    }
12834514f5e3Sopenharmony_ci    JSHandle<BigInt> result = CreateBigint(thread, needLen);
12844514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
12854514f5e3Sopenharmony_ci    if (shift == 0) {
12864514f5e3Sopenharmony_ci        std::copy(bigint->GetData(), bigint->GetData() + len, result->GetData());
12874514f5e3Sopenharmony_ci    } else {
12884514f5e3Sopenharmony_ci        uint32_t carry = 0;
12894514f5e3Sopenharmony_ci        uint32_t index = 0;
12904514f5e3Sopenharmony_ci        while (index < len) {
12914514f5e3Sopenharmony_ci            uint32_t value = bigint->GetDigit(index);
12924514f5e3Sopenharmony_ci            result->SetDigit(index, (value << shift) | carry);
12934514f5e3Sopenharmony_ci            carry = value >> (DATEBITS - shift);
12944514f5e3Sopenharmony_ci            index++;
12954514f5e3Sopenharmony_ci        }
12964514f5e3Sopenharmony_ci        if (carry != 0) {
12974514f5e3Sopenharmony_ci            ASSERT(neeedAddOne);
12984514f5e3Sopenharmony_ci            result->SetDigit(index, carry);
12994514f5e3Sopenharmony_ci        }
13004514f5e3Sopenharmony_ci    }
13014514f5e3Sopenharmony_ci    return result;
13024514f5e3Sopenharmony_ci}
13034514f5e3Sopenharmony_ci
13044514f5e3Sopenharmony_civoid BigInt::UnformattedRightShift(JSHandle<BigInt> bigint, uint32_t shift)
13054514f5e3Sopenharmony_ci{
13064514f5e3Sopenharmony_ci    RightShift(bigint, bigint, 0, shift);
13074514f5e3Sopenharmony_ci}
13084514f5e3Sopenharmony_ci
13094514f5e3Sopenharmony_cibool BigInt::SpecialMultiplyAndSub(JSHandle<BigInt> u, JSHandle<BigInt> v, uint32_t q, JSHandle<BigInt> qv,
13104514f5e3Sopenharmony_ci                                   uint32_t pos)
13114514f5e3Sopenharmony_ci{
13124514f5e3Sopenharmony_ci    uint32_t lastCarry = 0;
13134514f5e3Sopenharmony_ci    uint32_t lastHigh = 0;
13144514f5e3Sopenharmony_ci    uint32_t len = v->GetLength();
13154514f5e3Sopenharmony_ci    // Calculate multiplication first
13164514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < len; ++i) {
13174514f5e3Sopenharmony_ci        uint32_t value = v->GetDigit(i);
13184514f5e3Sopenharmony_ci        uint32_t carry = 0;
13194514f5e3Sopenharmony_ci        uint32_t high = 0;
13204514f5e3Sopenharmony_ci        std::tie(high, value) = Mul(value, q);
13214514f5e3Sopenharmony_ci        // The current value plus the high and carry of the last calculation
13224514f5e3Sopenharmony_ci        value = BigIntHelper::AddHelper(value, lastHigh, carry);
13234514f5e3Sopenharmony_ci        value = BigIntHelper::AddHelper(value, lastCarry, carry);
13244514f5e3Sopenharmony_ci        qv->SetDigit(i, value);
13254514f5e3Sopenharmony_ci        // Record the new high bit and carry for the next round
13264514f5e3Sopenharmony_ci        lastCarry = carry;
13274514f5e3Sopenharmony_ci        lastHigh = high;
13284514f5e3Sopenharmony_ci    }
13294514f5e3Sopenharmony_ci    qv->SetDigit(len, lastHigh + lastCarry);
13304514f5e3Sopenharmony_ci
13314514f5e3Sopenharmony_ci    // Next, subtract
13324514f5e3Sopenharmony_ci    uint32_t lastBorrow = 0;
13334514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < qv->GetLength(); ++i) {
13344514f5e3Sopenharmony_ci        uint32_t borrow = 0;
13354514f5e3Sopenharmony_ci        uint32_t value = BigIntHelper::SubHelper(u->GetDigit(pos + i), qv->GetDigit(i), borrow);
13364514f5e3Sopenharmony_ci        value = BigIntHelper::SubHelper(value, lastBorrow, borrow);
13374514f5e3Sopenharmony_ci        u->SetDigit(pos + i, value);
13384514f5e3Sopenharmony_ci        lastBorrow = borrow;
13394514f5e3Sopenharmony_ci    }
13404514f5e3Sopenharmony_ci
13414514f5e3Sopenharmony_ci    return lastBorrow > 0;
13424514f5e3Sopenharmony_ci}
13434514f5e3Sopenharmony_ci
13444514f5e3Sopenharmony_ciuint32_t BigInt::SpecialAdd(JSHandle<BigInt> u, JSHandle<BigInt> v, uint32_t pos)
13454514f5e3Sopenharmony_ci{
13464514f5e3Sopenharmony_ci    uint32_t lastCarry = 0;
13474514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < v->GetLength(); ++i) {
13484514f5e3Sopenharmony_ci        uint32_t carry = 0;
13494514f5e3Sopenharmony_ci        uint32_t value = BigIntHelper::AddHelper(u->GetDigit(pos + i), v->GetDigit(i), carry);
13504514f5e3Sopenharmony_ci        value = BigIntHelper::AddHelper(value, lastCarry, carry);
13514514f5e3Sopenharmony_ci        u->SetDigit(pos + i, value);
13524514f5e3Sopenharmony_ci        lastCarry = carry;
13534514f5e3Sopenharmony_ci    }
13544514f5e3Sopenharmony_ci    return lastCarry;
13554514f5e3Sopenharmony_ci}
13564514f5e3Sopenharmony_ci
13574514f5e3Sopenharmony_ciuint32_t BigInt::ImproveAccuracy(uint32_t vHighest, uint32_t vHighestNext, uint32_t UHighest,
13584514f5e3Sopenharmony_ci                                 uint32_t UHighestNext, uint32_t q)
13594514f5e3Sopenharmony_ci{
13604514f5e3Sopenharmony_ci    uint32_t high = 0;
13614514f5e3Sopenharmony_ci    uint32_t low = 0;
13624514f5e3Sopenharmony_ci    std::tie(high, low) = Mul(q, vHighestNext);
13634514f5e3Sopenharmony_ci    while (high > UHighest || (high == UHighest && low > UHighestNext)) {
13644514f5e3Sopenharmony_ci        q--;
13654514f5e3Sopenharmony_ci        UHighest += vHighest;
13664514f5e3Sopenharmony_ci        // if r is less than the current base, continue the next round of inspection. Here,
13674514f5e3Sopenharmony_ci        // we confirm whether r is greater than the current base by judging whether r overflows
13684514f5e3Sopenharmony_ci        if (UHighest < vHighest) {
13694514f5e3Sopenharmony_ci            break;
13704514f5e3Sopenharmony_ci        }
13714514f5e3Sopenharmony_ci        std::tie(high, low) = Mul(q, vHighestNext);
13724514f5e3Sopenharmony_ci    }
13734514f5e3Sopenharmony_ci    return q;
13744514f5e3Sopenharmony_ci}
13754514f5e3Sopenharmony_ci
13764514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::DivideAndRemainderWithBigintDivisor(JSThread *thread, JSHandle<BigInt> dividend,
13774514f5e3Sopenharmony_ci                                                             JSHandle<BigInt> divisor,
13784514f5e3Sopenharmony_ci                                                             JSMutableHandle<BigInt> &remainder)
13794514f5e3Sopenharmony_ci{
13804514f5e3Sopenharmony_ci    uint32_t divisorLen = divisor->GetLength();
13814514f5e3Sopenharmony_ci    // the length of the quota is the length of the dividend minus the divisor
13824514f5e3Sopenharmony_ci    uint32_t quotientLen = dividend->GetLength() - divisorLen;
13834514f5e3Sopenharmony_ci    JSMutableHandle<BigInt> quotient(thread, JSTaggedValue::Null());
13844514f5e3Sopenharmony_ci    if (remainder.GetTaggedValue().IsNull()) {
13854514f5e3Sopenharmony_ci        quotient.Update(CreateBigint(thread, quotientLen + 1));
13864514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
13874514f5e3Sopenharmony_ci    }
13884514f5e3Sopenharmony_ci    // format the divisor and dividend so that the highest order of the divisor is
13894514f5e3Sopenharmony_ci    // greater than or equal to half of uint32_t
13904514f5e3Sopenharmony_ci    ASSERT(divisorLen > 0);
13914514f5e3Sopenharmony_ci    uint32_t leadingZeros = base::CountLeadingZeros(divisor->GetDigit(divisorLen - 1));
13924514f5e3Sopenharmony_ci    JSHandle<BigInt> v = FormatLeftShift(thread, leadingZeros, divisor, false);
13934514f5e3Sopenharmony_ci    JSHandle<BigInt> u = FormatLeftShift(thread, leadingZeros, dividend, true);
13944514f5e3Sopenharmony_ci    // qv is used to store the result of quotient * divisor of each round
13954514f5e3Sopenharmony_ci    JSHandle<BigInt> qv = CreateBigint(thread, divisorLen + 1);
13964514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
13974514f5e3Sopenharmony_ci    uint32_t vHighest = v->GetDigit(divisorLen - 1);
13984514f5e3Sopenharmony_ci    for (int i = static_cast<int>(quotientLen); i >= 0; --i) {
13994514f5e3Sopenharmony_ci        uint32_t currentUHighest = u->GetDigit(i + divisorLen);
14004514f5e3Sopenharmony_ci        uint32_t r = 0;
14014514f5e3Sopenharmony_ci        uint32_t q = DivideAndRemainder(currentUHighest, u->GetDigit(i + divisorLen - 1), vHighest, r);
14024514f5e3Sopenharmony_ci        // VHighest = currentUHighest means that q may be equal to the current base
14034514f5e3Sopenharmony_ci        // In the current program, the current base is the maximum value of uint32 plus 1
14044514f5e3Sopenharmony_ci        if (vHighest == currentUHighest) {
14054514f5e3Sopenharmony_ci            q = std::numeric_limits<uint32_t>::max();
14064514f5e3Sopenharmony_ci        } else {
14074514f5e3Sopenharmony_ci            uint32_t vHighestNext = v->GetDigit(divisorLen - 2); // 2 : Get the second most significant bit
14084514f5e3Sopenharmony_ci            uint32_t currentUHighestNext = u->GetDigit(i + divisorLen - 2); // 2 : ditto
14094514f5e3Sopenharmony_ci
14104514f5e3Sopenharmony_ci            // The following operations will make q only 1 greater than the value we want in most cases,
14114514f5e3Sopenharmony_ci            // and will not be less than it
14124514f5e3Sopenharmony_ci            q = ImproveAccuracy(vHighest, vHighestNext, r, currentUHighestNext, q);
14134514f5e3Sopenharmony_ci        }
14144514f5e3Sopenharmony_ci        // multiplication and subtraction
14154514f5e3Sopenharmony_ci        if (SpecialMultiplyAndSub(u, v, q, qv, i)) {
14164514f5e3Sopenharmony_ci            q--;
14174514f5e3Sopenharmony_ci            uint32_t carry = SpecialAdd(u, v, i);
14184514f5e3Sopenharmony_ci            u->SetDigit(i + divisorLen, u->GetDigit(i + divisorLen) + carry);
14194514f5e3Sopenharmony_ci        }
14204514f5e3Sopenharmony_ci        if (remainder.GetTaggedValue().IsNull()) {
14214514f5e3Sopenharmony_ci            quotient->SetDigit(i, q);
14224514f5e3Sopenharmony_ci        }
14234514f5e3Sopenharmony_ci    }
14244514f5e3Sopenharmony_ci    if (!remainder.GetTaggedValue().IsNull()) {
14254514f5e3Sopenharmony_ci        // at the beginning of this procedure, we performed the left shift operation.
14264514f5e3Sopenharmony_ci        // Here, we get the correct result by shifting the same number of digits to the right
14274514f5e3Sopenharmony_ci        UnformattedRightShift(u, leadingZeros);
14284514f5e3Sopenharmony_ci        remainder.Update(u);
14294514f5e3Sopenharmony_ci    }
14304514f5e3Sopenharmony_ci    return quotient;
14314514f5e3Sopenharmony_ci}
14324514f5e3Sopenharmony_ci
14334514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::DivideAndRemainderWithUint32Divisor(JSThread *thread, JSHandle<BigInt> dividend,
14344514f5e3Sopenharmony_ci                                                             uint32_t divisor, JSMutableHandle<BigInt> &remainder)
14354514f5e3Sopenharmony_ci{
14364514f5e3Sopenharmony_ci    uint32_t r = 0;
14374514f5e3Sopenharmony_ci    JSMutableHandle<BigInt> quotient(thread, JSTaggedValue::Null());
14384514f5e3Sopenharmony_ci    if (!remainder.GetTaggedValue().IsNull()) {
14394514f5e3Sopenharmony_ci        for (int i = static_cast<int>(dividend->GetLength()) - 1; i >= 0; --i) {
14404514f5e3Sopenharmony_ci            DivideAndRemainder(r, dividend->GetDigit(i), divisor, r);
14414514f5e3Sopenharmony_ci            remainder.Update(Uint32ToBigInt(thread, r));
14424514f5e3Sopenharmony_ci        }
14434514f5e3Sopenharmony_ci    } else {
14444514f5e3Sopenharmony_ci        quotient.Update(CreateBigint(thread, dividend->GetLength()));
14454514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
14464514f5e3Sopenharmony_ci        for (int i = static_cast<int>(dividend->GetLength()) - 1; i >= 0; --i) {
14474514f5e3Sopenharmony_ci            uint32_t q = DivideAndRemainder(r, dividend->GetDigit(i), divisor, r);
14484514f5e3Sopenharmony_ci            quotient->SetDigit(i, q);
14494514f5e3Sopenharmony_ci        }
14504514f5e3Sopenharmony_ci    }
14514514f5e3Sopenharmony_ci    return quotient;
14524514f5e3Sopenharmony_ci}
14534514f5e3Sopenharmony_ci
14544514f5e3Sopenharmony_ci// The algorithm here refers to algorithm D in Volume 2 of <The Art of Computer Programming>
14554514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::Divide(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y)
14564514f5e3Sopenharmony_ci{
14574514f5e3Sopenharmony_ci    if (y->IsZero()) {
14584514f5e3Sopenharmony_ci        JSHandle<BigInt> bigint(thread, JSTaggedValue::Exception());
14594514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "Division by zero", bigint);
14604514f5e3Sopenharmony_ci    }
14614514f5e3Sopenharmony_ci    // returns 0 if x is less than y
14624514f5e3Sopenharmony_ci    JSMutableHandle<BigInt> quotient(thread, JSTaggedValue::Null());
14634514f5e3Sopenharmony_ci    bool sign = x->GetSign() != y->GetSign();
14644514f5e3Sopenharmony_ci    ComparisonResult compare = AbsolutelyCompare(*x, *y);
14654514f5e3Sopenharmony_ci    if (compare == ComparisonResult::LESS) {
14664514f5e3Sopenharmony_ci        return Int32ToBigInt(thread, 0);
14674514f5e3Sopenharmony_ci    }
14684514f5e3Sopenharmony_ci    if (compare == ComparisonResult::EQUAL) {
14694514f5e3Sopenharmony_ci        quotient.Update(Int32ToBigInt(thread, 1));
14704514f5e3Sopenharmony_ci        quotient->SetSign(sign);
14714514f5e3Sopenharmony_ci        return quotient;
14724514f5e3Sopenharmony_ci    }
14734514f5e3Sopenharmony_ci    // if y is 1, return +x or -x
14744514f5e3Sopenharmony_ci    if (y->IsUint32() && y->GetDigit(0) == 1) {
14754514f5e3Sopenharmony_ci        if (sign == x->GetSign()) {
14764514f5e3Sopenharmony_ci            return x;
14774514f5e3Sopenharmony_ci        }
14784514f5e3Sopenharmony_ci        return UnaryMinus(thread, x);
14794514f5e3Sopenharmony_ci    }
14804514f5e3Sopenharmony_ci    JSMutableHandle<BigInt> remainder(thread, JSTaggedValue::Null());
14814514f5e3Sopenharmony_ci    if (y->IsUint32()) {
14824514f5e3Sopenharmony_ci        // When the divisor is uint32_t, we have a faster and simpler algorithm to calculate
14834514f5e3Sopenharmony_ci        quotient.Update(DivideAndRemainderWithUint32Divisor(thread, x, y->GetDigit(0), remainder));
14844514f5e3Sopenharmony_ci    } else {
14854514f5e3Sopenharmony_ci        ASSERT(y->GetLength() >= 1); // 1 : Entering the current branch length must be greater than 1
14864514f5e3Sopenharmony_ci        JSHandle<BigInt> newBigint = DivideAndRemainderWithBigintDivisor(thread, x, y, remainder);
14874514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
14884514f5e3Sopenharmony_ci        quotient.Update(newBigint);
14894514f5e3Sopenharmony_ci    }
14904514f5e3Sopenharmony_ci    ASSERT(quotient.GetTaggedValue().IsBigInt());
14914514f5e3Sopenharmony_ci    quotient->SetSign(sign);
14924514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, quotient);
14934514f5e3Sopenharmony_ci}
14944514f5e3Sopenharmony_ci
14954514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::Remainder(JSThread *thread, JSHandle<BigInt> n, JSHandle<BigInt> d)
14964514f5e3Sopenharmony_ci{
14974514f5e3Sopenharmony_ci    if (d->IsZero()) {
14984514f5e3Sopenharmony_ci        JSHandle<BigInt> bigint(thread, JSTaggedValue::Exception());
14994514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "Division by zero", bigint);
15004514f5e3Sopenharmony_ci    }
15014514f5e3Sopenharmony_ci    ComparisonResult compare = AbsolutelyCompare(*n, *d);
15024514f5e3Sopenharmony_ci    if (n->IsZero() || compare == ComparisonResult::LESS) {
15034514f5e3Sopenharmony_ci        return n;
15044514f5e3Sopenharmony_ci    }
15054514f5e3Sopenharmony_ci    if (compare == ComparisonResult::EQUAL || (d->IsUint32() && d->GetDigit(0) == 1)) {
15064514f5e3Sopenharmony_ci        return Int32ToBigInt(thread, 0);
15074514f5e3Sopenharmony_ci    }
15084514f5e3Sopenharmony_ci    JSMutableHandle<BigInt> remainder(thread, JSTaggedValue::Undefined());
15094514f5e3Sopenharmony_ci    if (d->IsUint32()) {
15104514f5e3Sopenharmony_ci        // When the divisor is uint32_t, we have a faster and simpler algorithm to calculate
15114514f5e3Sopenharmony_ci        DivideAndRemainderWithUint32Divisor(thread, n, d->GetDigit(0), remainder);
15124514f5e3Sopenharmony_ci    } else {
15134514f5e3Sopenharmony_ci        ASSERT(d->GetLength() > 1); // 1 : Entering the current branch length must be greater than 1
15144514f5e3Sopenharmony_ci        DivideAndRemainderWithBigintDivisor(thread, n, d, remainder);
15154514f5e3Sopenharmony_ci        RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
15164514f5e3Sopenharmony_ci    }
15174514f5e3Sopenharmony_ci    ASSERT(remainder.GetTaggedValue().IsBigInt());
15184514f5e3Sopenharmony_ci    remainder->SetSign(n->GetSign());
15194514f5e3Sopenharmony_ci    return BigIntHelper::RightTruncate(thread, remainder);
15204514f5e3Sopenharmony_ci}
15214514f5e3Sopenharmony_ci
15224514f5e3Sopenharmony_ciJSHandle<BigInt> BigInt::FloorMod(JSThread *thread, JSHandle<BigInt> leftVal, JSHandle<BigInt> rightVal)
15234514f5e3Sopenharmony_ci{
15244514f5e3Sopenharmony_ci    JSHandle<BigInt> remainder = Remainder(thread, leftVal, rightVal);
15254514f5e3Sopenharmony_ci    RETURN_HANDLE_IF_ABRUPT_COMPLETION(BigInt, thread);
15264514f5e3Sopenharmony_ci    if (leftVal->GetSign() && !remainder->IsZero()) {
15274514f5e3Sopenharmony_ci        return Add(thread, remainder, rightVal);
15284514f5e3Sopenharmony_ci    }
15294514f5e3Sopenharmony_ci    return remainder;
15304514f5e3Sopenharmony_ci}
15314514f5e3Sopenharmony_ci
15324514f5e3Sopenharmony_ciJSTaggedValue BigInt::AsUintN(JSThread *thread, JSTaggedNumber &bits, JSHandle<BigInt> bigint)
15334514f5e3Sopenharmony_ci{
15344514f5e3Sopenharmony_ci    JSTaggedNumber number = JSTaggedValue::ToNumber(thread, bits);
15354514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
15364514f5e3Sopenharmony_ci    int64_t bit  = base::NumberHelper::DoubleToInt64(number.GetNumber());
15374514f5e3Sopenharmony_ci    if (bit == 0) {
15384514f5e3Sopenharmony_ci        return Int32ToBigInt(thread, 0).GetTaggedValue();
15394514f5e3Sopenharmony_ci    }
15404514f5e3Sopenharmony_ci    if (bigint->IsZero()) {
15414514f5e3Sopenharmony_ci        return bigint.GetTaggedValue();
15424514f5e3Sopenharmony_ci    }
15434514f5e3Sopenharmony_ci    JSHandle<BigInt> exponent = Uint64ToBigInt(thread, bit);
15444514f5e3Sopenharmony_ci    JSHandle<BigInt> base = Int64ToBigInt(thread, 2); // 2 : base value
15454514f5e3Sopenharmony_ci    if (bit >= kMaxLengthBits && !bigint->GetSign()) {
15464514f5e3Sopenharmony_ci        return bigint.GetTaggedValue();
15474514f5e3Sopenharmony_ci    }
15484514f5e3Sopenharmony_ci    JSHandle<BigInt> tValue = Exponentiate(thread, base, exponent);
15494514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
15504514f5e3Sopenharmony_ci    return FloorMod(thread, bigint, tValue).GetTaggedValue();
15514514f5e3Sopenharmony_ci}
15524514f5e3Sopenharmony_ci
15534514f5e3Sopenharmony_ciJSTaggedValue BigInt::AsintN(JSThread *thread, JSTaggedNumber &bits, JSHandle<BigInt> bigint)
15544514f5e3Sopenharmony_ci{
15554514f5e3Sopenharmony_ci    JSTaggedNumber number = JSTaggedValue::ToNumber(thread, bits);
15564514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
15574514f5e3Sopenharmony_ci    int64_t bit  = base::NumberHelper::DoubleToInt64(number.GetNumber());
15584514f5e3Sopenharmony_ci    if (bit == 0) {
15594514f5e3Sopenharmony_ci        return Int32ToBigInt(thread, 0).GetTaggedValue();
15604514f5e3Sopenharmony_ci    }
15614514f5e3Sopenharmony_ci    if (bigint->IsZero()) {
15624514f5e3Sopenharmony_ci        return bigint.GetTaggedValue();
15634514f5e3Sopenharmony_ci    }
15644514f5e3Sopenharmony_ci    JSHandle<BigInt> exp = Int64ToBigInt(thread, bit);
15654514f5e3Sopenharmony_ci    JSHandle<BigInt> exponent = Int64ToBigInt(thread, bit - 1);
15664514f5e3Sopenharmony_ci    JSHandle<BigInt> base = Int64ToBigInt(thread, 2); // 2 : base value
15674514f5e3Sopenharmony_ci    if (bit >= kMaxLengthBits && !bigint->GetSign()) {
15684514f5e3Sopenharmony_ci        return bigint.GetTaggedValue();
15694514f5e3Sopenharmony_ci    }
15704514f5e3Sopenharmony_ci    JSHandle<BigInt> tValue = Exponentiate(thread, base, exp);
15714514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
15724514f5e3Sopenharmony_ci    JSHandle<BigInt> modValue = FloorMod(thread, bigint, tValue);
15734514f5e3Sopenharmony_ci    JSHandle<BigInt> resValue = Exponentiate(thread, base, exponent);
15744514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
15754514f5e3Sopenharmony_ci    // If mod ≥ 2bits - 1, return ℤ(mod - 2bits); otherwise, return (mod).
15764514f5e3Sopenharmony_ci    if (Compare(*resValue, *modValue) != ComparisonResult::GREAT) {
15774514f5e3Sopenharmony_ci        return Subtract(thread, modValue, tValue).GetTaggedValue();
15784514f5e3Sopenharmony_ci    }
15794514f5e3Sopenharmony_ci    return modValue.GetTaggedValue();
15804514f5e3Sopenharmony_ci}
15814514f5e3Sopenharmony_ci
15824514f5e3Sopenharmony_cistatic JSTaggedNumber CalculateNumber(const uint64_t &sign, const uint64_t &mantissa, uint64_t &exponent)
15834514f5e3Sopenharmony_ci{
15844514f5e3Sopenharmony_ci    exponent = (exponent + base::DOUBLE_EXPONENT_BIAS) << base::DOUBLE_SIGNIFICAND_SIZE;
15854514f5e3Sopenharmony_ci    uint64_t doubleBit = sign | exponent | mantissa;
15864514f5e3Sopenharmony_ci    double res = 0;
15874514f5e3Sopenharmony_ci    if (memcpy_s(&res, sizeof(res), &doubleBit, sizeof(doubleBit)) != EOK) {
15884514f5e3Sopenharmony_ci        LOG_FULL(FATAL) << "memcpy_s failed";
15894514f5e3Sopenharmony_ci        UNREACHABLE();
15904514f5e3Sopenharmony_ci    }
15914514f5e3Sopenharmony_ci    return JSTaggedNumber(res);
15924514f5e3Sopenharmony_ci}
15934514f5e3Sopenharmony_ci
15944514f5e3Sopenharmony_cistatic JSTaggedNumber Rounding(const uint64_t &sign, uint64_t &mantissa, uint64_t &exponent, bool needRound)
15954514f5e3Sopenharmony_ci{
15964514f5e3Sopenharmony_ci    if (needRound || (mantissa & 1) == 1) {
15974514f5e3Sopenharmony_ci        ++mantissa;
15984514f5e3Sopenharmony_ci        if ((mantissa >> base::DOUBLE_SIGNIFICAND_SIZE) != 0) {
15994514f5e3Sopenharmony_ci            mantissa = 0;
16004514f5e3Sopenharmony_ci            exponent++;
16014514f5e3Sopenharmony_ci            if (exponent > base::DOUBLE_EXPONENT_BIAS) {
16024514f5e3Sopenharmony_ci                return JSTaggedNumber(sign ? -base::POSITIVE_INFINITY : base::POSITIVE_INFINITY);
16034514f5e3Sopenharmony_ci            }
16044514f5e3Sopenharmony_ci        }
16054514f5e3Sopenharmony_ci    }
16064514f5e3Sopenharmony_ci    return CalculateNumber(sign, mantissa, exponent);
16074514f5e3Sopenharmony_ci}
16084514f5e3Sopenharmony_ci
16094514f5e3Sopenharmony_ciJSTaggedNumber BigInt::BigIntToNumber(JSHandle<BigInt> bigint)
16104514f5e3Sopenharmony_ci{
16114514f5e3Sopenharmony_ci    if (bigint->IsZero()) {
16124514f5e3Sopenharmony_ci        return JSTaggedNumber(0);
16134514f5e3Sopenharmony_ci    }
16144514f5e3Sopenharmony_ci    uint32_t bigintLen = bigint->GetLength();
16154514f5e3Sopenharmony_ci    ASSERT(bigintLen > 0);
16164514f5e3Sopenharmony_ci    uint32_t BigintHead = bigint->GetDigit(bigintLen - 1);
16174514f5e3Sopenharmony_ci    uint32_t leadingZeros = base::CountLeadingZeros(BigintHead);
16184514f5e3Sopenharmony_ci    int bigintBitLen = static_cast<int>(bigintLen * BigInt::DATEBITS - leadingZeros);
16194514f5e3Sopenharmony_ci    // if Significant bits greater than 1024 then double is infinity
16204514f5e3Sopenharmony_ci    bool bigintSign = bigint->GetSign();
16214514f5e3Sopenharmony_ci    if (bigintBitLen > (base::DOUBLE_EXPONENT_BIAS + 1)) {
16224514f5e3Sopenharmony_ci        return JSTaggedNumber(bigintSign ? -base::POSITIVE_INFINITY : base::POSITIVE_INFINITY);
16234514f5e3Sopenharmony_ci    }
16244514f5e3Sopenharmony_ci    uint64_t sign = bigintSign ? 1ULL << 63 : 0; // 63 : Set the sign bit of sign to 1
16254514f5e3Sopenharmony_ci    int needMoveBit = static_cast<int>(leadingZeros + BigInt::DATEBITS + 1);
16264514f5e3Sopenharmony_ci    // Align to the most significant bit, then right shift 12 bits so that the head of the mantissa is in place
16274514f5e3Sopenharmony_ci    uint64_t mantissa = (needMoveBit == 64) ? 0 :
16284514f5e3Sopenharmony_ci        ((static_cast<uint64_t>(BigintHead) << needMoveBit) >> 12); // 12 mantissa// just has 52 bits
16294514f5e3Sopenharmony_ci    int remainMantissaBits = needMoveBit - 12;
16304514f5e3Sopenharmony_ci    ASSERT(bigintBitLen > 0);
16314514f5e3Sopenharmony_ci    uint64_t exponent = static_cast<uint64_t>(bigintBitLen - 1);
16324514f5e3Sopenharmony_ci    int index = static_cast<int>(bigintLen - 1);
16334514f5e3Sopenharmony_ci    uint32_t digit = 0;
16344514f5e3Sopenharmony_ci    if (index > 0) {
16354514f5e3Sopenharmony_ci        digit = bigint->GetDigit(--index);
16364514f5e3Sopenharmony_ci    } else {
16374514f5e3Sopenharmony_ci        return CalculateNumber(sign, mantissa, exponent);
16384514f5e3Sopenharmony_ci    }
16394514f5e3Sopenharmony_ci    // pad unset mantissa
16404514f5e3Sopenharmony_ci    if (static_cast<uint32_t>(remainMantissaBits) >= BigInt::DATEBITS) {
16414514f5e3Sopenharmony_ci        mantissa |= (static_cast<uint64_t>(digit) << (remainMantissaBits - BigInt::DATEBITS));
16424514f5e3Sopenharmony_ci        remainMantissaBits -= BigInt::DATEBITS;
16434514f5e3Sopenharmony_ci        index--;
16444514f5e3Sopenharmony_ci    }
16454514f5e3Sopenharmony_ci    if (remainMantissaBits > 0 && index >= 0) {
16464514f5e3Sopenharmony_ci        digit = bigint->GetDigit(index);
16474514f5e3Sopenharmony_ci        mantissa |= (static_cast<uint64_t>(digit) >> (BigInt::DATEBITS - remainMantissaBits));
16484514f5e3Sopenharmony_ci        remainMantissaBits -= BigInt::DATEBITS;
16494514f5e3Sopenharmony_ci    }
16504514f5e3Sopenharmony_ci    // After the mantissa is filled, if the bits of bigint have not been used up, consider the rounding problem
16514514f5e3Sopenharmony_ci    // The remaining bits of the current digit
16524514f5e3Sopenharmony_ci    if (remainMantissaBits > 0) {
16534514f5e3Sopenharmony_ci        return CalculateNumber(sign, mantissa, exponent);
16544514f5e3Sopenharmony_ci    }
16554514f5e3Sopenharmony_ci    int remainDigitBits = 0;
16564514f5e3Sopenharmony_ci    if (remainMantissaBits < 0) {
16574514f5e3Sopenharmony_ci        remainDigitBits = -remainMantissaBits;
16584514f5e3Sopenharmony_ci    } else {
16594514f5e3Sopenharmony_ci        if (index <= 0) {
16604514f5e3Sopenharmony_ci            return CalculateNumber(sign, mantissa, exponent);
16614514f5e3Sopenharmony_ci        }
16624514f5e3Sopenharmony_ci        digit = bigint->GetDigit(index--);
16634514f5e3Sopenharmony_ci        remainDigitBits = BigInt::DATEBITS;
16644514f5e3Sopenharmony_ci    }
16654514f5e3Sopenharmony_ci    uint32_t temp = 1ULL << (remainDigitBits - 1);
16664514f5e3Sopenharmony_ci    if (!(digit & temp)) {
16674514f5e3Sopenharmony_ci        return CalculateNumber(sign, mantissa, exponent);
16684514f5e3Sopenharmony_ci    }
16694514f5e3Sopenharmony_ci    if ((digit & (temp - 1)) != 0) {
16704514f5e3Sopenharmony_ci        return Rounding(sign, mantissa, exponent, true);
16714514f5e3Sopenharmony_ci    }
16724514f5e3Sopenharmony_ci    while (index > 0) {
16734514f5e3Sopenharmony_ci        if (bigint->GetDigit(--index) != 0) {
16744514f5e3Sopenharmony_ci            return Rounding(sign, mantissa, exponent, true);
16754514f5e3Sopenharmony_ci        }
16764514f5e3Sopenharmony_ci    }
16774514f5e3Sopenharmony_ci    return Rounding(sign, mantissa, exponent, false);
16784514f5e3Sopenharmony_ci}
16794514f5e3Sopenharmony_ci
16804514f5e3Sopenharmony_cistatic int CompareToBitsLen(JSHandle<BigInt> bigint, int numBitLen, int &leadingZeros)
16814514f5e3Sopenharmony_ci{
16824514f5e3Sopenharmony_ci    uint32_t bigintLen = bigint->GetLength();
16834514f5e3Sopenharmony_ci    ASSERT(bigintLen > 0);
16844514f5e3Sopenharmony_ci    uint32_t BigintHead = bigint->GetDigit(bigintLen - 1);
16854514f5e3Sopenharmony_ci    leadingZeros = static_cast<int>(base::CountLeadingZeros(BigintHead));
16864514f5e3Sopenharmony_ci    int bigintBitLen = static_cast<int>(bigintLen * BigInt::DATEBITS) - leadingZeros;
16874514f5e3Sopenharmony_ci    bool bigintSign = bigint->GetSign();
16884514f5e3Sopenharmony_ci    if (bigintBitLen > numBitLen) {
16894514f5e3Sopenharmony_ci        return bigintSign ? 0 : 1;
16904514f5e3Sopenharmony_ci    }
16914514f5e3Sopenharmony_ci
16924514f5e3Sopenharmony_ci    if (bigintBitLen < numBitLen) {
16934514f5e3Sopenharmony_ci        return bigintSign ? 1 : 0;
16944514f5e3Sopenharmony_ci    }
16954514f5e3Sopenharmony_ci    return -1;
16964514f5e3Sopenharmony_ci}
16974514f5e3Sopenharmony_ci
16984514f5e3Sopenharmony_ciComparisonResult BigInt::CompareWithNumber(JSHandle<BigInt> bigint, JSHandle<JSTaggedValue> number)
16994514f5e3Sopenharmony_ci{
17004514f5e3Sopenharmony_ci    double num = number->GetNumber();
17014514f5e3Sopenharmony_ci    bool numberSign = num < 0;
17024514f5e3Sopenharmony_ci    if (std::isnan(num)) {
17034514f5e3Sopenharmony_ci        return ComparisonResult::UNDEFINED;
17044514f5e3Sopenharmony_ci    }
17054514f5e3Sopenharmony_ci    if (!std::isfinite(num)) {
17064514f5e3Sopenharmony_ci        return (!numberSign ?  ComparisonResult::LESS : ComparisonResult::GREAT);
17074514f5e3Sopenharmony_ci    }
17084514f5e3Sopenharmony_ci    // Bit operations must be of integer type
17094514f5e3Sopenharmony_ci    uint64_t bits = 0;
17104514f5e3Sopenharmony_ci    if (memcpy_s(&bits, sizeof(bits), &num, sizeof(num)) != EOK) {
17114514f5e3Sopenharmony_ci        LOG_FULL(FATAL) << "memcpy_s failed";
17124514f5e3Sopenharmony_ci        UNREACHABLE();
17134514f5e3Sopenharmony_ci    }
17144514f5e3Sopenharmony_ci    int exponential = (bits >> base::DOUBLE_SIGNIFICAND_SIZE) & 0x7FF;
17154514f5e3Sopenharmony_ci
17164514f5e3Sopenharmony_ci    // Take out bits 62-52 (11 bits in total) and subtract 1023
17174514f5e3Sopenharmony_ci    int integerDigits = exponential - base::DOUBLE_EXPONENT_BIAS;
17184514f5e3Sopenharmony_ci    uint64_t mantissa = (bits & base::DOUBLE_SIGNIFICAND_MASK) | base::DOUBLE_HIDDEN_BIT;
17194514f5e3Sopenharmony_ci    bool bigintSign = bigint->GetSign();
17204514f5e3Sopenharmony_ci    // Handling the opposite sign
17214514f5e3Sopenharmony_ci    if (!numberSign && bigintSign) {
17224514f5e3Sopenharmony_ci        return ComparisonResult::LESS;
17234514f5e3Sopenharmony_ci    } else if (numberSign && !bigintSign) {
17244514f5e3Sopenharmony_ci        return ComparisonResult::GREAT;
17254514f5e3Sopenharmony_ci    }
17264514f5e3Sopenharmony_ci    if (bigint->IsZero() && !num) {
17274514f5e3Sopenharmony_ci        return ComparisonResult::EQUAL;
17284514f5e3Sopenharmony_ci    }
17294514f5e3Sopenharmony_ci    if (bigint->IsZero() && num > 0) {
17304514f5e3Sopenharmony_ci        return ComparisonResult::LESS;
17314514f5e3Sopenharmony_ci    }
17324514f5e3Sopenharmony_ci
17334514f5e3Sopenharmony_ci    if (integerDigits < 0) {
17344514f5e3Sopenharmony_ci        return bigintSign ? ComparisonResult::LESS : ComparisonResult::GREAT;
17354514f5e3Sopenharmony_ci    }
17364514f5e3Sopenharmony_ci
17374514f5e3Sopenharmony_ci    // Compare the significant bits of bigint with the significant integer bits of double
17384514f5e3Sopenharmony_ci    int leadingZeros = 0;
17394514f5e3Sopenharmony_ci    int res = CompareToBitsLen(bigint, integerDigits + 1, leadingZeros);
17404514f5e3Sopenharmony_ci    if (res == 0) {
17414514f5e3Sopenharmony_ci        return ComparisonResult::LESS;
17424514f5e3Sopenharmony_ci    } else if (res == 1) {
17434514f5e3Sopenharmony_ci        return ComparisonResult::GREAT;
17444514f5e3Sopenharmony_ci    }
17454514f5e3Sopenharmony_ci    int mantissaSize = base::DOUBLE_SIGNIFICAND_SIZE; // mantissaSize
17464514f5e3Sopenharmony_ci    uint32_t bigintLen = bigint->GetLength();
17474514f5e3Sopenharmony_ci    int leftover = 0;
17484514f5e3Sopenharmony_ci    bool IsFirstInto = true;
17494514f5e3Sopenharmony_ci    ASSERT(bigintLen > 0);
17504514f5e3Sopenharmony_ci    for (int index = static_cast<int>(bigintLen - 1); index >= 0; --index) {
17514514f5e3Sopenharmony_ci        uint32_t doubleNum = 0;
17524514f5e3Sopenharmony_ci        uint32_t BigintNum = bigint->GetDigit(index);
17534514f5e3Sopenharmony_ci        if (IsFirstInto) {
17544514f5e3Sopenharmony_ci            IsFirstInto = false;
17554514f5e3Sopenharmony_ci            leftover = mantissaSize - BigInt::DATEBITS + leadingZeros + 1;
17564514f5e3Sopenharmony_ci            doubleNum = static_cast<uint32_t>(mantissa >> leftover);
17574514f5e3Sopenharmony_ci            mantissa = mantissa << (64 - leftover); // 64 : double bits
17584514f5e3Sopenharmony_ci            if (BigintNum > doubleNum) {
17594514f5e3Sopenharmony_ci                return bigintSign ? ComparisonResult::LESS : ComparisonResult::GREAT;
17604514f5e3Sopenharmony_ci            }
17614514f5e3Sopenharmony_ci            if (BigintNum < doubleNum) {
17624514f5e3Sopenharmony_ci                return bigintSign ? ComparisonResult::GREAT : ComparisonResult::LESS;
17634514f5e3Sopenharmony_ci            }
17644514f5e3Sopenharmony_ci        } else {
17654514f5e3Sopenharmony_ci            leftover -= BigInt::DATEBITS;
17664514f5e3Sopenharmony_ci            doubleNum = static_cast<uint32_t>(mantissa >> BigInt::DATEBITS);
17674514f5e3Sopenharmony_ci            mantissa = mantissa << BigInt::DATEBITS;
17684514f5e3Sopenharmony_ci            if (BigintNum > doubleNum) {
17694514f5e3Sopenharmony_ci                return bigintSign ? ComparisonResult::LESS : ComparisonResult::GREAT;
17704514f5e3Sopenharmony_ci            }
17714514f5e3Sopenharmony_ci            if (BigintNum < doubleNum) {
17724514f5e3Sopenharmony_ci                return bigintSign ? ComparisonResult::GREAT : ComparisonResult::LESS;
17734514f5e3Sopenharmony_ci            }
17744514f5e3Sopenharmony_ci            leftover -= BigInt::DATEBITS;
17754514f5e3Sopenharmony_ci        }
17764514f5e3Sopenharmony_ci    }
17774514f5e3Sopenharmony_ci
17784514f5e3Sopenharmony_ci    if (mantissa != 0) {
17794514f5e3Sopenharmony_ci        ASSERT(leftover > 0);
17804514f5e3Sopenharmony_ci        return bigintSign ? ComparisonResult::GREAT : ComparisonResult::LESS;
17814514f5e3Sopenharmony_ci    }
17824514f5e3Sopenharmony_ci    return ComparisonResult::EQUAL;
17834514f5e3Sopenharmony_ci}
17844514f5e3Sopenharmony_ci} // namespace
1785