mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-29 20:07:30 +09:00
Issue #2026 - Part 2b - Format BigInts representable as int64_t without first converting them to strings. https://bugzilla.mozilla.org/show_bug.cgi?id=1543677
This commit is contained in:
parent
d972016c23
commit
3ce9cf4deb
3 changed files with 63 additions and 12 deletions
|
|
@ -417,6 +417,13 @@ PartitionNumberPattern(JSContext* cx, UNumberFormat* nf, HandleValue x,
|
||||||
});
|
});
|
||||||
} else if(x.isBigInt()) {
|
} else if(x.isBigInt()) {
|
||||||
RootedBigInt bi(cx, x.toBigInt());
|
RootedBigInt bi(cx, x.toBigInt());
|
||||||
|
int64_t num;
|
||||||
|
|
||||||
|
if (BigInt::isInt64(bi, &num)) {
|
||||||
|
return CallICU(cx, [nf, num](UChar* chars, int32_t size, UErrorCode* status) {
|
||||||
|
return unum_formatInt64(nf, num, chars, size, nullptr, status);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
JSLinearString* str = BigInt::toString(cx, bi, 10);
|
JSLinearString* str = BigInt::toString(cx, bi, 10);
|
||||||
if (!str) {
|
if (!str) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -430,6 +437,7 @@ PartitionNumberPattern(JSContext* cx, UNumberFormat* nf, HandleValue x,
|
||||||
return unum_formatDecimal(nf, latinchars, length, chars, size, nullptr, status);
|
return unum_formatDecimal(nf, latinchars, length, chars, size, nullptr, status);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@
|
||||||
#include "mozilla/WrappingOperations.h"
|
#include "mozilla/WrappingOperations.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <limits>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|
@ -2211,6 +2212,43 @@ uint64_t BigInt::toUint64(BigInt* x) {
|
||||||
return digit;
|
return digit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BigInt::isInt64(BigInt* x, int64_t* result) {
|
||||||
|
MOZ_MAKE_MEM_UNDEFINED(result, sizeof(*result));
|
||||||
|
|
||||||
|
size_t length = x->digitLength();
|
||||||
|
if (length > (DigitBits == 32 ? 2 : 1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length == 0) {
|
||||||
|
*result = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t magnitude = x->digit(0);
|
||||||
|
if (DigitBits == 32 && length > 1) {
|
||||||
|
magnitude |= static_cast<uint64_t>(x->digit(1)) << 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x->isNegative()) {
|
||||||
|
constexpr uint64_t Int64MinMagnitude = uint64_t(1) << 63;
|
||||||
|
if (magnitude <= Int64MinMagnitude) {
|
||||||
|
*result = magnitude == Int64MinMagnitude
|
||||||
|
? std::numeric_limits<int64_t>::min()
|
||||||
|
: -AssertedCast<int64_t>(magnitude);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (magnitude <=
|
||||||
|
static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
|
||||||
|
*result = AssertedCast<int64_t>(magnitude);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Compute `2**bits - (x & (2**bits - 1))`. Used when treating BigInt values as
|
// Compute `2**bits - (x & (2**bits - 1))`. Used when treating BigInt values as
|
||||||
// arbitrary-precision two's complement signed integers.
|
// arbitrary-precision two's complement signed integers.
|
||||||
BigInt* BigInt::truncateAndSubFromPowerOfTwo(ExclusiveContext* cx, HandleBigInt x,
|
BigInt* BigInt::truncateAndSubFromPowerOfTwo(ExclusiveContext* cx, HandleBigInt x,
|
||||||
|
|
@ -2661,7 +2699,7 @@ double BigInt::numberValue(BigInt* x) {
|
||||||
if (length <= 64 / DigitBits) {
|
if (length <= 64 / DigitBits) {
|
||||||
uint64_t magnitude = x->digit(0);
|
uint64_t magnitude = x->digit(0);
|
||||||
if (DigitBits == 32 && length > 1) {
|
if (DigitBits == 32 && length > 1) {
|
||||||
magnitude |= uint64_t(x->digit(1)) << 32;
|
magnitude |= static_cast<uint64_t>(x->digit(1)) << 32;
|
||||||
}
|
}
|
||||||
const uint64_t MaxIntegralPrecisionDouble = uint64_t(1)
|
const uint64_t MaxIntegralPrecisionDouble = uint64_t(1)
|
||||||
<< (SignificandWidth + 1);
|
<< (SignificandWidth + 1);
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,11 @@ class BigInt final : public js::gc::TenuredCell {
|
||||||
static int64_t toInt64(BigInt* x);
|
static int64_t toInt64(BigInt* x);
|
||||||
static uint64_t toUint64(BigInt* x);
|
static uint64_t toUint64(BigInt* x);
|
||||||
|
|
||||||
|
// Return true if the BigInt is without loss of precision representable as an
|
||||||
|
// int64 and store the int64 value in the output. Otherwise return false and
|
||||||
|
// leave the value of the output parameter unspecified.
|
||||||
|
static bool isInt64(BigInt* x, int64_t* result);
|
||||||
|
|
||||||
static BigInt* asIntN(js::ExclusiveContext* cx, Handle<BigInt*> x, uint64_t bits);
|
static BigInt* asIntN(js::ExclusiveContext* cx, Handle<BigInt*> x, uint64_t bits);
|
||||||
static BigInt* asUintN(js::ExclusiveContext* cx, Handle<BigInt*> x, uint64_t bits);
|
static BigInt* asUintN(js::ExclusiveContext* cx, Handle<BigInt*> x, uint64_t bits);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue