Last active
February 15, 2021 12:46
-
-
Save JeffreySarnoff/919f92029ff7355d1340ae6683469ec7 to your computer and use it in GitHub Desktop.
benchmarking firstindex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using BenchmarkTools | |
const BT=BenchmarkTools.DEFAULT_PARAMETERS; | |
BT.samples=60_000; BT.time_tolerance=1/8192; | |
#= | |
IS{Int64} == Union{Int64, Symbol} | |
IS{Int32} == Union{Int32, Symbol} | |
=# | |
const IS = Union{I,Symbol} where {I<:Integer} | |
# test vars, length(chrs) == 96 | |
seqlen = (8, Tuple((16 * i for i=1:6))...,); | |
middles = (4, 12, Tuple(collect(8+(16 * i) for i=1:5))...,); | |
finals = deepcopy(seqlen) | |
chrs = Char.(Int('a'):Int('p')); | |
syms = Tuple(collect(Iterators.flatten(map(x->Symbol(x,i), chrs) for i=1:6))); | |
strs = string.(syms); | |
ints = Tuple(collect(1:length(syms))); | |
symseqs = collect(syms[1:n] for n in seqlen); | |
intseqs = collect(ints[1:n] for n in seqlen); | |
strseqs = collect(strs[1:n] for n in seqlen); | |
nt_ints = map((symseq,intseq)->NamedTuple{symseq}(intseq), symseqs, intseqs); | |
nt_strs = map((symseq,strseq)->NamedTuple{symseq}(strseq), symseqs, strseqs); | |
function indexof(item::T, seq::NTuple{N, T}) where {N,T} | |
if N < 33 | |
indexof_recur(item, seq) | |
else | |
indexof_iter(item, seq) | |
end | |
end | |
function indexof_recur(item::T, seq::NTuple{N, T}, idx=1) where {N,T} | |
item === first(seq) ? idx : indexof_recur(item, Base.tail(seq), idx+1) | |
end | |
indexof_recur(item::T, seq::Tuple{}, idx=1) where {T} = 0 | |
@inline function indexof_iter(item::T, seq::NTuple{N, T}) where {N,T} | |
equalsx = Base.Fix2(===, item) | |
idx = 1 | |
for x in seq | |
equalsx(x) && break | |
idx = idx + 1 | |
end | |
return idx > N ? 0 : idx | |
end | |
function indexof(item::T, seq::Vector{T}) where {T} | |
equalsx = Base.Fix2(===, item) | |
idx = 1 | |
for x in seq | |
equalsx(x) && break | |
idx = idx + 1 | |
end | |
return idx > length(seq) ? 0 : idx | |
end | |
#= | |
v1.7 | |
indexof(item, seq) best times | |
| seqlen | item | tuple ns | vector ns | | |
|--------|------|----------|-----------| | |
| 8 | 4 | 1.9 | 3.5 | | |
| 8 | 8 | 2.4 | 4.3 | | |
| 16 | 12 | 3.1 | 5.7 | | |
| 16 | 16 | 3.8 | 7.1 | | |
| 32 | 24 | 6.3 | 10.0 | | |
| 32 | 32 | 7.8 | 12.8 | | |
| 48 | 40 | 17.9 | 15.8 | | |
| 48 | 48 | 20.9 | 18.6 | | |
| 64 | 56 | 24.1 | 21.5 | | |
| 64 | 64 | 27.7 | 24.3 | | |
| 80 | 72 | 32.0 | 27.3 | | |
| 80 | 80 | 41.0 | 35.0 | | |
| 96 | 88 | 45.0 | 38.3 | | |
| 96 | 96 | 42.3 | 35.8 | | |
=# | |
#= | |
function indexfirst(x::T, seq::NTuple{N,T}) where {N,T} | |
if N < 33 | |
return indexfirst_rec(x, seq, 1) | |
else | |
return index_first(N, x, seq) | |
end | |
end | |
v1.7 | |
indexfirst(item, seq) | |
| seqlen | item | tuple ns | vector ns | | |
|--------|------|----------|-----------| | |
| 8 | 4 | 1.8 | 2.4 | | |
| 8 | 8 | 2.4 | 4.3 | | |
| 16 | 12 | 3.0 | 5.6 | | |
| 16 | 16 | 3.7 | 7.0 | | |
| 32 | 24 | 6.4 | 10.0 | | |
| 32 | 32 | 7.6 | 12.8 | | |
| 48 | 40 | 18.1 | 15.7 | | |
| 48 | 48 | 20.3 | 18.2 | | |
| 64 | 56 | 25.0 | 21.4 | | |
| 64 | 64 | 27.8 | 24.3 | | |
| 80 | 72 | 32.0 | 27.3 | | |
| 80 | 80 | 41.0 | 35.0 | | |
| 96 | 88 | 45.0 | 38.3 | | |
| 96 | 96 | 42.3 | 35.8 | | |
=# | |
#= | |
function btime(f, refarg1, refarg2; mulby=1.0e9, digits=2) | |
t1 = @belapsed $f($refarg1[], $refarg2[]) | |
t2 = @belapsed $f($refarg1[], $refarg2[]) | |
t3 = @belapsed $f($refarg1[], $refarg2[]) | |
t4 = @belapsed $f($refarg1[], $refarg2[]) | |
result = minimum((t1,t2,t3,t4)) | |
result = result * mulby | |
result = round(result, digits=digits, base=10) | |
return result | |
end | |
function testvals(i) | |
miditem = Ref(middles[i]) | |
finalitem = Ref(finals[i]) | |
tupl = Ref(intseqs[i]) | |
vect = Ref([intseqs[i]...]) | |
return (miditem, finalitem), (tupl, vect) | |
end | |
julia> fn = indexfirst; | |
julia> (miditem, finalitem), (tupl, vect) = testvals(1); (length=finalitem[],) | |
(length = 8,) | |
julia> (n= finalitem[], | |
tupl= (btime(fn, miditem, tupl), btime(fn, finalitem, tupl)), | |
vect=(btime(fn, miditem, vect), btime(fn, finalitem, vect))) | |
(n=8, tupl = (2.7, 3.4), vect = (4.1, 6.0)) | |
julia> btime(fn, miditem, tupl), btime(fn, finalitem, tupl) | |
3.3, 6.2 | |
julia> btime(fn, miditem, vect), btime(fn, finalitem, vect) | |
=# | |
function indexfirst(x::T, seq::NTuple{N,T}) where {N,T} | |
N < 17 && return indexfirst(Val(N), x, seq) | |
index_first(N, x, seq) | |
end | |
function indexfirst(x::T, seq::V) where {T,V<:AbstractVector{T}} | |
N = length(seq) | |
index_first(N, x, seq) | |
end | |
@inline function index_first(N, x, seq) | |
equalsx = Base.Fix2(===, x) | |
idx = 1 | |
for item in seq | |
equalsx(item) && break | |
idx = idx + 1 | |
end | |
return idx > N ? 0 : idx | |
end | |
function indexfirst(x::T, seq::NTuple{N,T}) where {N,T} | |
if N < 17 | |
return indexfirst(Val(N), x, seq) | |
elseif N < 33 | |
return indexfirst(x, seq, 1) | |
elseif N < 65 | |
result = indexfirst(x, seq[1:32], 1) | |
!iszero(result) && return result | |
result = indexfirst(x, seq[33:end], 1) | |
return iszero(result) ? 0 : result + 32 | |
elseif N < 129 | |
result = indexfirst(x, seq[1:64], 1) | |
!iszero(result) && return result | |
result = indexfirst(x, seq[65:end], 1) | |
return iszero(result) ? 0 : result + 64 | |
else | |
error("seqlen of $N is not supported") | |
end | |
end | |
# recursive | |
# fast with no allocation until N>32, then 1000x slower | |
function indexfirst(x::T, seq::NTuple{N,T}, i=1) where {N,T} | |
x === first(seq) ? i : indexfirst(x, Base.tail(seq), i+1) | |
end | |
indexfirst(x::T, seq::Tuple{}) where {T} = 0 | |
indexfirst(x::T, seq::Tuple{}, i) where {T} = 0 | |
# unrolled | |
# fastest, limit N == 16 | |
function indexfirst(::Val{1}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
( | |
x === tup[1] && return 1) | |
return 0 | |
end | |
function indexfirst(::Val{2}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
(( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) | |
return 0 | |
end | |
function indexfirst(::Val{3}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) | |
return 0 | |
end | |
function indexfirst(::Val{4}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
(((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) || | |
x === tup[4] && return 4) | |
return 0 | |
end | |
function indexfirst(::Val{5}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
((((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) || | |
x === tup[4] && return 4) || | |
x === tup[5] && return 5) | |
return 0 | |
end | |
function indexfirst(::Val{6}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
(((((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) || | |
x === tup[4] && return 4) || | |
x === tup[5] && return 5) || | |
x === tup[6] && return 6) | |
return 0 | |
end | |
function indexfirst(::Val{7}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
((((((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) || | |
x === tup[4] && return 4) || | |
x === tup[5] && return 5) || | |
x === tup[6] && return 6) || | |
x === tup[7] && return 7) | |
return 0 | |
end | |
function indexfirst(::Val{8}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
(((((((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) || | |
x === tup[4] && return 4) || | |
x === tup[5] && return 5) || | |
x === tup[6] && return 6) || | |
x === tup[7] && return 7) || | |
x === tup[8] && return 8) | |
return 0 | |
end | |
function indexfirst(::Val{9}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
((((((((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) || | |
x === tup[4] && return 4) || | |
x === tup[5] && return 5) || | |
x === tup[6] && return 6) || | |
x === tup[7] && return 7) || | |
x === tup[8] && return 8) || | |
x === tup[9] && return 9) | |
return 0 | |
end | |
function indexfirst(::Val{10}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
(((((((((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) || | |
x === tup[4] && return 4) || | |
x === tup[5] && return 5) || | |
x === tup[6] && return 6) || | |
x === tup[7] && return 7) || | |
x === tup[8] && return 8) || | |
x === tup[9] && return 9) || | |
x === tup[10] && return 10) | |
return 0 | |
end | |
function indexfirst(::Val{11}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
((((((((((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) || | |
x === tup[4] && return 4) || | |
x === tup[5] && return 5) || | |
x === tup[6] && return 6) || | |
x === tup[7] && return 7) || | |
x === tup[8] && return 8) || | |
x === tup[9] && return 9) || | |
x === tup[10] && return 10) || | |
x === tup[11] && return 11) | |
return 0 | |
end | |
function indexfirst(::Val{12}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
(((((((((((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) || | |
x === tup[4] && return 4) || | |
x === tup[5] && return 5) || | |
x === tup[6] && return 6) || | |
x === tup[7] && return 7) || | |
x === tup[8] && return 8) || | |
x === tup[9] && return 9) || | |
x === tup[10] && return 10) || | |
x === tup[11] && return 11) || | |
x === tup[12] && return 12) | |
return 0 | |
end | |
function indexfirst(::Val{13}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
((((((((((((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) || | |
x === tup[4] && return 4) || | |
x === tup[5] && return 5) || | |
x === tup[6] && return 6) || | |
x === tup[7] && return 7) || | |
x === tup[8] && return 8) || | |
x === tup[9] && return 9) || | |
x === tup[10] && return 10) || | |
x === tup[11] && return 11) || | |
x === tup[12] && return 12) || | |
x === tup[13] && return 13) | |
return 0 | |
end | |
function indexfirst(::Val{14}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
(((((((((((((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) || | |
x === tup[4] && return 4) || | |
x === tup[5] && return 5) || | |
x === tup[6] && return 6) || | |
x === tup[7] && return 7) || | |
x === tup[8] && return 8) || | |
x === tup[9] && return 9) || | |
x === tup[10] && return 10) || | |
x === tup[11] && return 11) || | |
x === tup[12] && return 12) || | |
x === tup[13] && return 13) || | |
x === tup[14] && return 14) | |
return 0 | |
end | |
function indexfirst(::Val{15}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
((((((((((((((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) || | |
x === tup[4] && return 4) || | |
x === tup[5] && return 5) || | |
x === tup[6] && return 6) || | |
x === tup[7] && return 7) || | |
x === tup[8] && return 8) || | |
x === tup[9] && return 9) || | |
x === tup[10] && return 10) || | |
x === tup[11] && return 11) || | |
x === tup[12] && return 12) || | |
x === tup[13] && return 13) || | |
x === tup[14] && return 14) || | |
x === tup[15] && return 15) | |
return 0 | |
end | |
function indexfirst(::Val{16}, x::T, tup::NTuple{N, T}) where {N, T<:IS{Int}} | |
(((((((((((((((( | |
x === tup[1] && return 1) || | |
x === tup[2] && return 2) || | |
x === tup[3] && return 3) || | |
x === tup[4] && return 4) || | |
x === tup[5] && return 5) || | |
x === tup[6] && return 6) || | |
x === tup[7] && return 7) || | |
x === tup[8] && return 8) || | |
x === tup[9] && return 9) || | |
x === tup[10] && return 10) || | |
x === tup[11] && return 11) || | |
x === tup[12] && return 12) || | |
x === tup[13] && return 13) || | |
x === tup[14] && return 14) || | |
x === tup[15] && return 15) || | |
x === tup[16] && return 16) | |
return 0 | |
end | |
# unrolled k+ | |
function indexfirst(::Val{1}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
( | |
x === tup[k+1] && return 1) | |
return 0 | |
end | |
function indexfirst(::Val{2}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
(( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) | |
return 0 | |
end | |
function indexfirst(::Val{3}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) | |
return 0 | |
end | |
function indexfirst(::Val{4}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
(((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) || | |
x === tup[k+4] && return 4) | |
return 0 | |
end | |
function indexfirst(::Val{5}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
((((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) || | |
x === tup[k+4] && return 4) || | |
x === tup[k+5] && return 5) | |
return 0 | |
end | |
function indexfirst(::Val{6}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
(((((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) || | |
x === tup[k+4] && return 4) || | |
x === tup[k+5] && return 5) || | |
x === tup[k+6] && return 6) | |
return 0 | |
end | |
function indexfirst(::Val{7}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
((((((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) || | |
x === tup[k+4] && return 4) || | |
x === tup[k+5] && return 5) || | |
x === tup[k+6] && return 6) || | |
x === tup[k+7] && return 7) | |
return 0 | |
end | |
function indexfirst(::Val{8}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
(((((((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) || | |
x === tup[k+4] && return 4) || | |
x === tup[k+5] && return 5) || | |
x === tup[k+6] && return 6) || | |
x === tup[k+7] && return 7) || | |
x === tup[k+8] && return 8) | |
return 0 | |
end | |
function indexfirst(::Val{9}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
((((((((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) || | |
x === tup[k+4] && return 4) || | |
x === tup[k+5] && return 5) || | |
x === tup[k+6] && return 6) || | |
x === tup[k+7] && return 7) || | |
x === tup[k+8] && return 8) || | |
x === tup[k+9] && return 9) | |
return 0 | |
end | |
function indexfirst(::Val{10}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
(((((((((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) || | |
x === tup[k+4] && return 4) || | |
x === tup[k+5] && return 5) || | |
x === tup[k+6] && return 6) || | |
x === tup[k+7] && return 7) || | |
x === tup[k+8] && return 8) || | |
x === tup[k+9] && return 9) || | |
x === tup[k+10] && return 10) | |
return 0 | |
end | |
function indexfirst(::Val{11}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
((((((((((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) || | |
x === tup[k+4] && return 4) || | |
x === tup[k+5] && return 5) || | |
x === tup[k+6] && return 6) || | |
x === tup[k+7] && return 7) || | |
x === tup[k+8] && return 8) || | |
x === tup[k+9] && return 9) || | |
x === tup[k+10] && return 10) || | |
x === tup[k+11] && return 11) | |
return 0 | |
end | |
function indexfirst(::Val{12}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
(((((((((((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) || | |
x === tup[k+4] && return 4) || | |
x === tup[k+5] && return 5) || | |
x === tup[k+6] && return 6) || | |
x === tup[k+7] && return 7) || | |
x === tup[k+8] && return 8) || | |
x === tup[k+9] && return 9) || | |
x === tup[k+10] && return 10) || | |
x === tup[k+11] && return 11) || | |
x === tup[k+12] && return 12) | |
return 0 | |
end | |
function indexfirst(::Val{13}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
((((((((((((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) || | |
x === tup[k+4] && return 4) || | |
x === tup[k+5] && return 5) || | |
x === tup[k+6] && return 6) || | |
x === tup[k+7] && return 7) || | |
x === tup[k+8] && return 8) || | |
x === tup[k+9] && return 9) || | |
x === tup[k+10] && return 10) || | |
x === tup[k+11] && return 11) || | |
x === tup[k+12] && return 12) || | |
x === tup[k+13] && return 13) | |
return 0 | |
end | |
function indexfirst(::Val{14}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
(((((((((((((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) || | |
x === tup[k+4] && return 4) || | |
x === tup[k+5] && return 5) || | |
x === tup[k+6] && return 6) || | |
x === tup[k+7] && return 7) || | |
x === tup[k+8] && return 8) || | |
x === tup[k+9] && return 9) || | |
x === tup[k+10] && return 10) || | |
x === tup[k+11] && return 11) || | |
x === tup[k+12] && return 12) || | |
x === tup[k+13] && return 13) || | |
x === tup[k+14] && return 14) | |
return 0 | |
end | |
function indexfirst(::Val{15}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
((((((((((((((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) || | |
x === tup[k+4] && return 4) || | |
x === tup[k+5] && return 5) || | |
x === tup[k+6] && return 6) || | |
x === tup[k+7] && return 7) || | |
x === tup[k+8] && return 8) || | |
x === tup[k+9] && return 9) || | |
x === tup[k+10] && return 10) || | |
x === tup[k+11] && return 11) || | |
x === tup[k+12] && return 12) || | |
x === tup[k+13] && return 13) || | |
x === tup[k+14] && return 14) || | |
x === tup[k+15] && return 15) | |
return 0 | |
end | |
function indexfirst(::Val{16}, x::T, k::I, tup::NTuple{N, T}) where {N, I<:Integer, T<:IS{I}} | |
(((((((((((((((( | |
x === tup[k+1] && return 1) || | |
x === tup[k+2] && return 2) || | |
x === tup[k+3] && return 3) || | |
x === tup[k+4] && return 4) || | |
x === tup[k+5] && return 5) || | |
x === tup[k+6] && return 6) || | |
x === tup[k+7] && return 7) || | |
x === tup[k+8] && return 8) || | |
x === tup[k+9] && return 9) || | |
x === tup[k+10] && return 10) || | |
x === tup[k+11] && return 11) || | |
x === tup[k+12] && return 12) || | |
x === tup[k+13] && return 13) || | |
x === tup[k+14] && return 14) || | |
x === tup[k+15] && return 15) || | |
x === tup[k+16] && return 16) | |
return 0 | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment