zig icon indicating copy to clipboard operation
zig copied to clipboard

std.math: port `int_log10` from Rust

Open adriandelgado opened this issue 1 year ago • 5 comments

A straight forward port of int_log10 from the Rust standard library, including tests.

In theory, this makes it possible to accurately compute log10 of any integer, from u1 to u65535. However, due to a compiler bug, currently it only gives accurate results up to u136.

Even with limitations, the proposed implementation it's an improvement because currently the compiler segfaults when trying to use integers bigger than u128 and gives wrong results even when it works.

I've been learning Zig for 2 weeks, sorry for any mistakes or non idiomatic code.

adriandelgado avatar Mar 07 '23 02:03 adriandelgado

Incidentally, that bug is soon going to be fixed :) https://github.com/jacobly0/zig/commit/c1d16a2b80e258a126ed496dab09a8a7c26f8468

jedisct1 avatar Mar 07 '23 12:03 jedisct1

Cool. I was thinking about this too. I saw that std.math.log10 accepted integers, but didn't advertise that there was a round-trip float conversion:

https://github.com/ziglang/zig/blob/36d47dd1991f0ccd7a9673075624f09500cc415e/lib/std/math/log10.zig#L13-L25

and so produced incorrect results for large-ish integers near a power of 10. The first such example is std.math.log10(999_999_999_999_998), which produces 15 instead of 14 (like 999_999_999_999_997).

As a possible follow-up, given the accepted proposal for @log2 to work for integers (https://github.com/ziglang/zig/issues/13642), should @log10 work for integers too?

Just in case it's helpful/interesting for anybody reading, here's some resources that I'm aware of:

  • https://internals.rust-lang.org/t/worth-optimizing-ilog10/18294 - Rust discussion of optimizing ilog10 further (I'm not suggesting trying that now)
  • https://da-data.blogspot.com/2023/02/integer-log10-in-rust-and-c.html
  • https://lemire.me/blog/2021/06/03/computing-the-number-of-digits-of-an-integer-even-faster/

Rust shipped this only recently, with 1.67.0 (2023-01-26):

  • https://www.github.com/rust-lang/rust/issues/70887
  • https://blog.rust-lang.org/2023/01/26/Rust-1.67.0.html#stabilized-apis

ee7 avatar Mar 07 '23 13:03 ee7

Those are some interesting resources for further optimizations, I wasn't aware of them.

Also, I wanted to improve @log10 to accept integers too because of #13642, but that is a more difficult task for a noob (too much compiler internals).

Seeing how this PR fails a lot of tests, postponing @log10 was the right call.

adriandelgado avatar Mar 07 '23 17:03 adriandelgado

Due to #14816 being fixed I rebased and cleaned the history to try again. I also increased the test cases up to u512 which should be possible now.

adriandelgado avatar Mar 08 '23 02:03 adriandelgado

It seems like only the LLVM backend can divide big ints for now...

adriandelgado avatar Mar 10 '23 01:03 adriandelgado

I skipped some tests similar to #14482

adriandelgado avatar Mar 22 '23 18:03 adriandelgado

Thank you, good work!

andrewrk avatar Apr 10 '23 17:04 andrewrk