I'm trying to understand how JS engines convert a JS Number (Float64) to a 32-bit signed integer. I read that one can quickly convert a 64 bit float to a 32 bit signed integer with the bitwise OR like:
-8589934590 | 0 // which gives 2
I can't understand where does the 2 come from. According to the spec, the ToInt32 algorithm does this (the bold text is mine, not the spec's):
let int32bit = 8589934590 % 2**32 // 4294967294 which has 32 bit length 0b11111111111111111111111111111110
int32bit
which equals -2
(Even if we consider 0b11111111111111111111111111111110
an unsigned integer, then it's greater 2³¹ and int32bit - 2³² still equals -2
Could someone, please, explain, do I correctly understand the ToInt32 algorithm and the bitwise OR operator?
Your step 4 is wrong. Modulo is defined by the spec as:
The notation “x modulo y” (y must be finite and nonzero) computes a value k of the same sign as y (or zero) such that abs(k) < abs(y) and x-k = q × y for some integer q.
So -8589934590 is our x, and 2**32 is our y, from that we also know that k must be positive. If we choose q = -1 we can solve the equation to k = -4294967294. That is however not a valid solution, as k (negative) does not have the same sign as y (positive). If we choose q = -2 instead, we get k = 2.
So for negative numbers x and positive numbers y, q * y will always have to result in a smaller number than x for k to be positive. Thus if we are transforming that to positive numbers (like you did), we are looking for the larger multiple of the number not the smaller one. E.g. if we take 2 % 3, that'll return 2 (2 - 2 = 3 * 0), whereas -2 modulo 3 will return 1 (-2 -1 = 3 * -1).