Remix.run Logo
ivankra 2 days ago

My favorite trick: NaN boxing. NaN's aren't just for errors, but also for smuggling other data inside. For a double, you have whopping 53 bits of payload, enough to cram in a pointer and maybe a type tag, and many javascript engines do (since JS numbers are double's after all)

https://wingolog.org/archives/2011/05/18/value-representatio...

https://piotrduperas.com/posts/nan-boxing

Arnavion 2 days ago | parent | next [-]

It is also how RISC-V floating point registers are required to store floats of smaller widths. Eg if your CPU supports 64-bit floats (D extension), its FPU registers will be 64-bit wide. If you use an instruction to load a 16-bit float (Zfh extension) into such a register, it will be boxed into a negative quiet NaN with all bits above the lower 16 bits set to 1.

pklausler 2 days ago | parent | prev [-]

52 bits of payload, and at least one bit must be set.

ivankra 2 days ago | parent [-]

You can put stuff into the sign bit too, that makes 53. Yeah, the lower 52 bits can't all be zero - that'd be ±INF, but the other 2^53-2 values are all yours to use.

pklausler 2 days ago | parent [-]

It's possible for the sign bit of a NaN to be changed by a "non-arithmetic" operation that doesn't trap on the NaN, so don't put anything precious in there.