mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 05:17:35 +00:00
LibJS: Implement a basic Intl mathematical value
The Intl mathematical value is much like ECMA-262's mathematical value in that it is meant to represent an arbitrarily precise number. The Intl MV further allows positive/negative infinity, negative zero, and NaN. This implementation is *not* arbitrarily precise. Rather, it is a replacement for the use of Value within Intl.NumberFormat. The exact syntax of the Intl MV is still being worked on, but abstracting this away into its own class will allow hooking in the finalized Intl MV more easily, and makes implementing Intl.NumberFormat.formatRange easier. Note the methods added here are essentially the same as the static helpers in Intl/NumberFormat.cpp.
This commit is contained in:
parent
99b79766cd
commit
0026e9a4c8
4 changed files with 454 additions and 0 deletions
105
Userland/Libraries/LibJS/Runtime/Intl/MathematicalValue.h
Normal file
105
Userland/Libraries/LibJS/Runtime/Intl/MathematicalValue.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Checked.h>
|
||||
#include <AK/Variant.h>
|
||||
#include <LibCrypto/BigInt/SignedBigInteger.h>
|
||||
#include <LibJS/Runtime/Value.h>
|
||||
|
||||
namespace JS::Intl {
|
||||
|
||||
// https://tc39.es/proposal-intl-numberformat-v3/out/numberformat/proposed.html#intl-mathematical-value
|
||||
class MathematicalValue {
|
||||
public:
|
||||
enum class Symbol {
|
||||
PositiveInfinity,
|
||||
NegativeInfinity,
|
||||
NegativeZero,
|
||||
NotANumber,
|
||||
};
|
||||
|
||||
MathematicalValue() = default;
|
||||
|
||||
explicit MathematicalValue(double value)
|
||||
: m_value(value_from_number(value))
|
||||
{
|
||||
}
|
||||
|
||||
explicit MathematicalValue(Crypto::SignedBigInteger value)
|
||||
: m_value(move(value))
|
||||
{
|
||||
}
|
||||
|
||||
explicit MathematicalValue(Symbol symbol)
|
||||
: m_value(symbol)
|
||||
{
|
||||
}
|
||||
|
||||
MathematicalValue(Value value)
|
||||
: m_value(value.is_number()
|
||||
? value_from_number(value.as_double())
|
||||
: ValueType(value.as_bigint().big_integer()))
|
||||
{
|
||||
}
|
||||
|
||||
bool is_number() const;
|
||||
double as_number() const;
|
||||
|
||||
bool is_bigint() const;
|
||||
Crypto::SignedBigInteger const& as_bigint() const;
|
||||
|
||||
bool is_mathematical_value() const;
|
||||
bool is_positive_infinity() const;
|
||||
bool is_negative_infinity() const;
|
||||
bool is_negative_zero() const;
|
||||
bool is_nan() const;
|
||||
|
||||
void negate();
|
||||
|
||||
MathematicalValue plus(Checked<i32> addition) const;
|
||||
MathematicalValue plus(MathematicalValue const& addition) const;
|
||||
|
||||
MathematicalValue minus(Checked<i32> subtraction) const;
|
||||
MathematicalValue minus(MathematicalValue const& subtraction) const;
|
||||
|
||||
MathematicalValue multiplied_by(Checked<i32> multiplier) const;
|
||||
MathematicalValue multiplied_by(MathematicalValue const& multiplier) const;
|
||||
|
||||
MathematicalValue divided_by(Checked<i32> divisor) const;
|
||||
MathematicalValue divided_by(MathematicalValue const& divisor) const;
|
||||
|
||||
MathematicalValue multiplied_by_power(Checked<i32> exponent) const;
|
||||
MathematicalValue divided_by_power(Checked<i32> exponent) const;
|
||||
|
||||
bool modulo_is_zero(Checked<i32> mod) const;
|
||||
|
||||
int logarithmic_floor() const;
|
||||
|
||||
bool is_equal_to(MathematicalValue const&) const;
|
||||
bool is_less_than(MathematicalValue const&) const;
|
||||
|
||||
bool is_negative() const;
|
||||
bool is_positive() const;
|
||||
bool is_zero() const;
|
||||
|
||||
String to_string() const;
|
||||
Value to_value(GlobalObject&) const;
|
||||
|
||||
private:
|
||||
using ValueType = Variant<double, Crypto::SignedBigInteger, Symbol>;
|
||||
|
||||
static ValueType value_from_number(double number);
|
||||
|
||||
// NOTE: The specific alignment is to avoid an UBSAN error with Clang i686, due to Clang
|
||||
// disagreeing with UBSAN on the alignment of doubles. See:
|
||||
// https://github.com/llvm/llvm-project/issues/54845
|
||||
// https://github.com/SerenityOS/serenity/issues/13614
|
||||
alignas(8) ValueType m_value { 0.0 };
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue