tc39 / proposal-bigint-math

Draft specification for supporting BigInts in JavaScript’s Math methods.

Home Page:https://tc39.es/proposal-bigint-math/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Count leading zeroes

dead-claudia opened this issue · comments

Where you omitted Math.clz32, you could replace that with Math.clzN(bigint, N), where the bigint is to be interpreted as an N-bit number.

In particular, Math.clzN(bigint, 64) could be accelerated on x64 and ARM, and if the bigint can't fit in a single 64-bit number, it can still be checked very efficiently by roughly this algorithm:

// For 32-bit - 64-bit will be similar
let m = Math.min(N, bigint.byteLength << 2)
let n = m & ~3
let i = 0

while (i < n) {
  let b = bigint.getUint32(i, true)
  if (b !== 0) {
    return (i << 3) + Math.clz32(b)
  }
  i += 4
}

if (i < m) {
  return Math.min(m, (i << 3) + Math.clz32(bigint.getUint32(i, true)))
}

return m

Thank you for raising this issue. Looking at the TC39 notes from 2014-01, it looks like the Committee’s intent was to have the language’s clz method(s) map to a single “efficient low-level primitive”; they also referred to a possible future clz64 in this vein.

[@BrendanEich] CLZ - for cases when you're doing DSP-level hacking, and want to count the number of populated bits. Also important for native-to-js compilers, there is an intrinsic for this in GCC and Clang.

In contrast to 32/64-bit leading zeros, I’m not sure what arbitrary-length leading zeroes would be useful for. Do you have a particular specific use case in mind?

I vaguely remember a delegate saying somewhere that they are loathe to add more “low-level” operations like clz32 to Math, but I could be mistaken. (I hope that this aversion is not absolute—I am planning to propose a separate proposal for a CPU-accelerated Math.popcnt.)

I think that I will probably treat this similarly to modular exponentiation in #1 and that I will keep this particular proposal limited in scope to extending the existing Math methods only.

That is to say, like Math.modExp, I expect a Math.clzN (or even a Math.clz64) to generate enough committee concerns to warrant its own separate, future proposal.

A clz64 would be acceptable, too. I was just following the pattern of asUintN, as an explicit bit length of some form is required, whether it be static (as you're suggesting) or dynamic (as per my initial suggestion).

You have a good point in that BigInt.asUintN is also a precedent. In any case, I think creating a Math.clzWhatever may make sense but would probably be best left to a separate future proposal; hope that’s understandable.

I think I’ll probably close this for now, in favor of a future proposal. The Committee reasonably wanted me to greatly reduce the functions covered by this proposal. We can deal with >32-bit leading zeroes in a future proposal. Thanks!