uiua icon indicating copy to clipboard operation
uiua copied to clipboard

Special case parse in base 10

Open ndren opened this issue 5 months ago • 2 comments

This PR special cases base 10 integer parsing to speed it up using the Rust stdlib.

Some code I used to test (run locally, I don't have a wasm build)

N ← 1e6
⊃($LongNumsFill ⊙◌⍜now⋕₁₀ ⬚@0 °⋕ ⇡ N
| $LongNumsBoxed ⊙◌⍜now⋕₁₀ °⋕ ⇡ N
| $ShortNumsFill ⊙◌⍜now⋕₁₀ ⬚@0 °⋕ ▽ (÷10 N) ⇡ 10
| $ShortNumsBox ⊙◌⍜now⋕₁₀ °⋕ ▽ (÷10 N) ⇡ 10
)
Metric main PR Speedup (%)
LongNumsFill 0.494306 0.355260 28.13%
LongNumsBoxed 0.626325 0.479558 23.43%
ShortNumsFill 0.351373 0.316105 10.04%
ShortNumsBox 0.493949 0.447104 9.48%

Note this code parses f64 more accurately than the code that was previously in use, so for some edge cases it would behave differently by a few ULP. Is that acceptable? (What's nice about this is that it now matches the results of using a float literal, since it now rounds correctly)

Example:

⋕₁₀ "3.14159265358979285"
# Before: π
# After: ~π

ndren avatar Nov 14 '25 14:11 ndren

Specifying π and co to the maximum precision should parse to π.

kaikalii avatar Nov 14 '25 17:11 kaikalii

Specifying π and co to the maximum precision should parse to π.

Yeah that's fine, and it does, in the example I gave the string value rounds correctly to nextafter(pi, -inf) but the code currently thinks the value rounds to exactly pi, which it does not.

The only downside is if some code relies on the incorrectly rounded results that are currently calculated.

ndren avatar Nov 14 '25 23:11 ndren

More examples before/after:

DetectPi ← ⍚(⍣(↙₄|∘)◇⊢pretty)⋕₁₀ °⋕ ↘₁÷ ⇡ 12
≡DetectPi[π τ η]

Before:

┌─                                                                          
╷ "π"│"η"  │"τ/6" │"τ/8" │"0.62"│"τ/12"│"0.44"│"0.39"│"0.34"│"0.31"│"0.28"  
  ───┼─────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────  
  "τ"│"π"  │"τ/3" │"η"   │"τ/5" │"τ/6" │"0.89"│"τ/8" │"~τ/9"│"0.62"│"0.57"  
  ───┼─────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────  
  "η"│"τ/8"│"τ/12"│"0.39"│"0.31"│"0.26"│"0.22"│"0.19"│"0.17"│"0.15"│"0.14"  

After:

┌─                                                                          
╷ "π"│"η"  │"τ/6" │"τ/8" │"0.62"│"τ/12"│"0.44"│"0.39"│"0.34"│"0.31"│"0.28"  
  ───┼─────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────  
  "τ"│"π"  │"τ/3" │"η"   │"τ/5" │"τ/6" │"0.89"│"τ/8" │"τ/9" │"0.62"│"0.57"  
  ───┼─────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────┼──────  
  "η"│"τ/8"│"τ/12"│"0.39"│"0.31"│"0.26"│"0.22"│"0.19"│"0.17"│"0.15"│"0.14"  
                                                                           ┘

So it still parses fractions of pi correctly, but also now can detect them more accurately for edge cases (see the tau/9 case where it now sees it as exactly tau/9 rather than ~tau/9)

ndren avatar Nov 17 '25 18:11 ndren