The change to explicitly note mathematical values broke the definition of modulo in the spec:
The notation โ_x_ modulo _t_ _y_โ (_y_ must be finite and nonzero) computes a value _k_ of the same sign as _y_ (or zero) such that abs _t_(_k_) <_t_ abs _t_(_y_) and _x_ -_t_ _k_ = _q_ ร_t_ _y_ for some integer _t_ _q_.
where _t_ is either โ for mathematical numbers or ๐ฝ for IEEE doubles.
This definition of modulo works only when _t_ is โ. The formula it uses is not meant to be used with numbers that are not mathematical numbers and breaks badly when _t_ is ๐ฝ. There are multiple issues with finite precision and rounding, overflow, and underflow.
For example, this definition produces the nonsensical result that the exact IEEE double 200000000000000032๐ฝ modulo๐ฝ 100๐ฝ is, among other things, 19๐ฝ because 200000000000000032๐ฝ -๐ฝ 19๐ฝ = 2000000000000000๐ฝ ร๐ฝ 100๐ฝ. The correct answer, of course, is 32๐ฝ.
Similarly, by this definition, 4๐ฝ modulo 2๐ฝ evaluates to, among other things, 1.74e-75๐ฝ because 4๐ฝ -๐ฝ 1.74e-75๐ฝ = 2๐ฝ ร๐ฝ 2๐ฝ.
To fix it, use the formula only for the mathematical definition of modulo. If you need to define modulo on ๐ฝ, do it by converting to and from mathematical numbers.
@waldemarhorwat Would you be willing to send a PR with your suggested fix?
cc @littledan @caiolima
@michaelficarra will do. It's a bit tricky because I don't want to define it for things like ยฑโ and NaN so I need to go through every point of use to see if those can arise. There are also some issues with the definition of _abs_ in this section.
Looking forward to seeing the PR for this.
For reference, some places in ES2019 where modulo is used on Number values:
Having seen so many other bugs introduced by #1135, I've now come to the conclusion that, rather than trying to hack modulo, exponentiation, addition, subtraction, counters, etc., the best way to fix them is to revert #1135 and instead explicitly mark the places where Number or Decimal arithmetic should be used. See #1964.
It seems like the fix for this issue is quite simple, to make modulo only in terms of โ and disallow parameterizing it. Are there any downsides to this fix?
@littledan: Yes, that's what I'd recommend doing for modulo (and exponentiation, etc.).
Modulo also seems inconsistent when dealing with negatives. Mathematical Operations specifies that the result has the sign of the divisor, while Number::remainder specifies that the result has the sign of the dividend.
So modulo behaves one way and Number::remainder behaves another. That's not really an inconsistency, not in the sense of the spec contradicting itself.