mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-19 15:32:31 +00:00
LibJS: Standardize spec prose for Math.sumPrecise
This commit is contained in:
parent
9674210ef8
commit
9c85a16aeb
Notes:
github-actions[bot]
2025-04-29 11:34:39 +00:00
Author: https://github.com/trflynn89
Commit: 9c85a16aeb
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4514
1 changed files with 65 additions and 63 deletions
|
@ -1025,25 +1025,15 @@ static TwoSumResult two_sum(double x, double y)
|
|||
return { hi, lo };
|
||||
}
|
||||
|
||||
// https://tc39.es/proposal-math-sum/#sec-math.sumprecise
|
||||
ThrowCompletionOr<Value> MathObject::sum_precise_impl(VM& vm, Value iterable)
|
||||
// 2 Math.sumPrecise ( items ), https://tc39.es/proposal-math-sum/#sec-math.sumprecise
|
||||
JS_DEFINE_NATIVE_FUNCTION(MathObject::sumPrecise)
|
||||
{
|
||||
constexpr double MAX_DOUBLE = 1.79769313486231570815e+308; // std::numeric_limits<double>::max()
|
||||
constexpr double PENULTIMATE_DOUBLE = 1.79769313486231550856e+308; // std::nextafter(DBL_MAX, 0)
|
||||
constexpr double MAX_ULP = MAX_DOUBLE - PENULTIMATE_DOUBLE;
|
||||
constexpr double POW_2_1023 = 8.98846567431158e+307; // 2^1023
|
||||
static constexpr double MAX_DOUBLE = 1.79769313486231570815e+308; // std::numeric_limits<double>::max()
|
||||
static constexpr double PENULTIMATE_DOUBLE = 1.79769313486231550856e+308; // std::nextafter(DBL_MAX, 0)
|
||||
static constexpr double MAX_ULP = MAX_DOUBLE - PENULTIMATE_DOUBLE;
|
||||
static constexpr double POW_2_1023 = 8.98846567431158e+307; // 2^1023
|
||||
|
||||
// 1. Perform ? RequireObjectCoercible(items).
|
||||
TRY(require_object_coercible(vm, iterable));
|
||||
|
||||
// 2. Let iteratorRecord be ? GetIterator(items, sync).
|
||||
auto using_iterator = TRY(iterable.get_method(vm, vm.well_known_symbol_iterator()));
|
||||
if (!using_iterator)
|
||||
return vm.throw_completion<TypeError>(ErrorType::NotIterable, iterable.to_string_without_side_effects());
|
||||
|
||||
auto iterator = TRY(get_iterator_from_method(vm, iterable, *using_iterator));
|
||||
|
||||
enum State {
|
||||
enum class State {
|
||||
MinusZero,
|
||||
PlusInfinity,
|
||||
MinusInfinity,
|
||||
|
@ -1051,7 +1041,15 @@ ThrowCompletionOr<Value> MathObject::sum_precise_impl(VM& vm, Value iterable)
|
|||
Finite
|
||||
};
|
||||
|
||||
// 3. Let state be minus-zero.
|
||||
auto items = vm.argument(0);
|
||||
|
||||
// 1. Perform ? RequireObjectCoercible(items).
|
||||
TRY(require_object_coercible(vm, items));
|
||||
|
||||
// 2. Let iteratorRecord be ? GetIterator(items, SYNC).
|
||||
auto iterator_record = TRY(get_iterator(vm, items, IteratorHint::Sync));
|
||||
|
||||
// 3. Let state be MINUS-ZERO.
|
||||
State state = State::MinusZero;
|
||||
|
||||
// 4. Let sum be 0.
|
||||
|
@ -1060,56 +1058,66 @@ ThrowCompletionOr<Value> MathObject::sum_precise_impl(VM& vm, Value iterable)
|
|||
u64 count = 0;
|
||||
Vector<double> partials;
|
||||
|
||||
// 6. Let next be not-started.
|
||||
// 7. Repeat, while next is not done
|
||||
// 6. Let next be NOT-STARTED.
|
||||
// 7. Repeat, while next is not DONE
|
||||
for (;;) {
|
||||
// a. Set next to ? IteratorStepValue(iteratorRecord).
|
||||
auto next = TRY(iterator_step_value(vm, iterator));
|
||||
|
||||
auto next = TRY(iterator_step_value(vm, iterator_record));
|
||||
if (!next.has_value())
|
||||
break;
|
||||
|
||||
// If next is not done, then
|
||||
// i. Set count to count + 1.
|
||||
count++;
|
||||
// ii. If count ≥ 2**53, then
|
||||
// 1. Let error be ThrowCompletion(a newly created RangeError object).
|
||||
// 2. Return ? IteratorClose(iteratorRecord, error).
|
||||
if (count >= (1ULL << 53))
|
||||
return iterator_close(vm, iterator, vm.throw_completion<RangeError>(ErrorType::ArrayMaxSize));
|
||||
auto next_value = next.value();
|
||||
|
||||
// iii. NOTE: The above case is not expected to be reached in practice and is included only so that implementations may rely on inputs being
|
||||
// "reasonably sized" without violating this specification.
|
||||
// b. If next is not DONE, then
|
||||
// i. Set count to count + 1.
|
||||
++count;
|
||||
|
||||
// ii. If count ≥ 2**53, then
|
||||
if (count >= (1ULL << 53)) {
|
||||
// 1. Let error be ThrowCompletion(a newly created RangeError object).
|
||||
auto error = vm.throw_completion<RangeError>(ErrorType::ArrayMaxSize);
|
||||
|
||||
// 2. Return ? IteratorClose(iteratorRecord, error).
|
||||
return iterator_close(vm, iterator_record, error);
|
||||
}
|
||||
|
||||
// iii. NOTE: The above case is not expected to be reached in practice and is included only so that implementations
|
||||
// may rely on inputs being "reasonably sized" without violating this specification.
|
||||
|
||||
// iv. If next is not a Number, then
|
||||
auto value = next.value();
|
||||
if (!value.is_number())
|
||||
if (!next_value.is_number()) {
|
||||
// 1. Let error be ThrowCompletion(a newly created TypeError object).
|
||||
auto error = vm.throw_completion<TypeError>(ErrorType::IsNotA, next_value, "number");
|
||||
|
||||
// 2. Return ? IteratorClose(iteratorRecord, error).
|
||||
return iterator_close(vm, iterator, vm.throw_completion<TypeError>(ErrorType::IsNotA, value.to_string_without_side_effects(), "number"));
|
||||
return iterator_close(vm, iterator_record, error);
|
||||
}
|
||||
|
||||
// v. Let n be next.
|
||||
auto n = value.as_double();
|
||||
auto n = next_value.as_double();
|
||||
|
||||
// vi. If state is not not-a-number, then
|
||||
// vi. If state is not NOT-A-NUMBER, then
|
||||
if (state != State::NotANumber) {
|
||||
// 1. If n is NaN, then
|
||||
if (isnan(n)) {
|
||||
// a. Set state to not-a-number.
|
||||
if (next_value.is_nan()) {
|
||||
// a. Set state to NOT-A-NUMBER.
|
||||
state = State::NotANumber;
|
||||
} // 2. Else if n is +∞𝔽, then
|
||||
else if (Value(n).is_positive_infinity()) {
|
||||
// a. If state is minus-infinity, set state to not-a-number.
|
||||
// b. Else, set state to plus-infinity.
|
||||
state = (state == State::MinusInfinity) ? State::NotANumber : State::PlusInfinity;
|
||||
} // 3. Else if n is -∞𝔽, then
|
||||
else if (Value(n).is_negative_infinity()) {
|
||||
// a. If state is plus-infinity, set state to not-a-number.
|
||||
// b. Else, set state to minus-infinity.
|
||||
state = (state == State::PlusInfinity) ? State::NotANumber : State::MinusInfinity;
|
||||
} // 4. Else if n is not -0𝔽 and state is either minus-zero or finite, then
|
||||
else if (!Value(n).is_negative_zero() && (state == State::MinusZero || state == State::Finite)) {
|
||||
// a. Set state to finite.
|
||||
}
|
||||
// 2. Else if n is +∞𝔽, then
|
||||
else if (next_value.is_positive_infinity()) {
|
||||
// a. If state is MINUS-INFINITY, set state to NOT-A-NUMBER.
|
||||
// b. Else, set state to PLUS-INFINITY.
|
||||
state = state == State::MinusInfinity ? State::NotANumber : State::PlusInfinity;
|
||||
}
|
||||
// 3. Else if n is -∞𝔽, then
|
||||
else if (next_value.is_negative_infinity()) {
|
||||
// a. If state is PLUS-INFINITY, set state to NOT-A-NUMBER.
|
||||
// b. Else, set state to MINUS-INFINITY.
|
||||
state = state == State::PlusInfinity ? State::NotANumber : State::MinusInfinity;
|
||||
}
|
||||
// 4. Else if n is not -0𝔽 and state is either MINUS-ZERO or FINITE, then
|
||||
else if (!next_value.is_negative_zero() && (state == State::MinusZero || state == State::Finite)) {
|
||||
// a. Set state to FINITE.
|
||||
state = State::Finite;
|
||||
|
||||
// b. Set sum to sum + ℝ(n).
|
||||
|
@ -1159,19 +1167,19 @@ ThrowCompletionOr<Value> MathObject::sum_precise_impl(VM& vm, Value iterable)
|
|||
}
|
||||
}
|
||||
|
||||
// 8. If state is not-a-number, return NaN.
|
||||
// 8. If state is NOT-A-NUMBER, return NaN.
|
||||
if (state == State::NotANumber)
|
||||
return js_nan();
|
||||
|
||||
// 9. If state is plus-infinity, return +∞𝔽.
|
||||
// 9. If state is PLUS-INFINITY, return +∞𝔽.
|
||||
if (state == State::PlusInfinity)
|
||||
return js_infinity();
|
||||
|
||||
// 10. If state is minus-infinity, return -∞𝔽.
|
||||
// 10. If state is MINUS-INFINITY, return -∞𝔽.
|
||||
if (state == State::MinusInfinity)
|
||||
return js_negative_infinity();
|
||||
|
||||
// 11. If state is minus-zero, return -0𝔽.
|
||||
// 11. If state is MINUS-ZERO, return -0𝔽.
|
||||
if (state == State::MinusZero)
|
||||
return Value(-0.0);
|
||||
|
||||
|
@ -1241,13 +1249,7 @@ ThrowCompletionOr<Value> MathObject::sum_precise_impl(VM& vm, Value iterable)
|
|||
}
|
||||
}
|
||||
|
||||
return Value(hi);
|
||||
}
|
||||
|
||||
// https://tc39.es/proposal-math-sum/#sec-math.sumprecise
|
||||
JS_DEFINE_NATIVE_FUNCTION(MathObject::sumPrecise)
|
||||
{
|
||||
return sum_precise_impl(vm, vm.argument(0));
|
||||
return hi;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue