|
263 | 263 |
|
264 | 264 | @eval split_rest(t::Tuple, n::Int, i=1) = ($(Expr(:meta, :aggressive_constprop)); (t[i:end-n], t[end-n+1:end])) |
265 | 265 |
|
266 | | -# Use dispatch to avoid a branch in first |
267 | | -first(::Tuple{}) = throw(ArgumentError("tuple must be non-empty")) |
268 | | -first(t::Tuple) = t[1] |
| 266 | +function first(t::Tuple) |
| 267 | + f(t::Tuple) = t[1] |
| 268 | + function f(::Tuple{}) |
| 269 | + @noinline |
| 270 | + throw(ArgumentError("tuple must be non-empty")) |
| 271 | + end |
| 272 | + f(t) |
| 273 | +end |
269 | 274 |
|
270 | 275 | # eltype |
271 | 276 |
|
@@ -577,71 +582,82 @@ function _eq(t1::Any32, t2::Any32) |
577 | 582 | end |
578 | 583 |
|
579 | 584 | const tuplehash_seed = UInt === UInt64 ? 0x77cfa1eef01bca90 : 0xf01bca90 |
580 | | -hash(::Tuple{}, h::UInt) = h ⊻ tuplehash_seed |
581 | | -hash(t::Tuple, h::UInt) = hash(t[1], hash(tail(t), h)) |
582 | | -function hash(t::Any32, h::UInt) |
583 | | - out = h ⊻ tuplehash_seed |
584 | | - for i = length(t):-1:1 |
585 | | - out = hash(t[i], out) |
| 585 | +function hash(t::Tuple, h::UInt) |
| 586 | + f(::Tuple{}, h::UInt) = h ⊻ tuplehash_seed |
| 587 | + f(t::Tuple, h::UInt) = hash(t[1], hash(tail(t), h)) |
| 588 | + function f(t::Any32, h::UInt) |
| 589 | + out = h ⊻ tuplehash_seed |
| 590 | + for i = length(t):-1:1 |
| 591 | + out = hash(t[i], out) |
| 592 | + end |
| 593 | + return out |
586 | 594 | end |
587 | | - return out |
| 595 | + f(t, h) |
588 | 596 | end |
589 | 597 |
|
590 | | -<(::Tuple{}, ::Tuple{}) = false |
591 | | -<(::Tuple{}, ::Tuple) = true |
592 | | -<(::Tuple, ::Tuple{}) = false |
593 | 598 | function <(t1::Tuple, t2::Tuple) |
594 | | - a, b = t1[1], t2[1] |
595 | | - eq = (a == b) |
596 | | - if ismissing(eq) |
597 | | - return missing |
598 | | - elseif !eq |
599 | | - return a < b |
600 | | - end |
601 | | - return tail(t1) < tail(t2) |
602 | | -end |
603 | | -function <(t1::Any32, t2::Any32) |
604 | | - n1, n2 = length(t1), length(t2) |
605 | | - for i = 1:min(n1, n2) |
606 | | - a, b = t1[i], t2[i] |
| 599 | + f(::Tuple{}, ::Tuple{}) = false |
| 600 | + f(::Tuple{}, ::Tuple) = true |
| 601 | + f(::Tuple, ::Tuple{}) = false |
| 602 | + function f(t1::Tuple, t2::Tuple) |
| 603 | + a, b = t1[1], t2[1] |
607 | 604 | eq = (a == b) |
608 | 605 | if ismissing(eq) |
609 | 606 | return missing |
610 | 607 | elseif !eq |
611 | | - return a < b |
| 608 | + return a < b |
| 609 | + end |
| 610 | + return tail(t1) < tail(t2) |
| 611 | + end |
| 612 | + function f(t1::Any32, t2::Any32) |
| 613 | + n1, n2 = length(t1), length(t2) |
| 614 | + for i = 1:min(n1, n2) |
| 615 | + a, b = t1[i], t2[i] |
| 616 | + eq = (a == b) |
| 617 | + if ismissing(eq) |
| 618 | + return missing |
| 619 | + elseif !eq |
| 620 | + return a < b |
| 621 | + end |
612 | 622 | end |
| 623 | + return n1 < n2 |
613 | 624 | end |
614 | | - return n1 < n2 |
| 625 | + f(t1, t2) |
615 | 626 | end |
616 | 627 |
|
617 | | -isless(::Tuple{}, ::Tuple{}) = false |
618 | | -isless(::Tuple{}, ::Tuple) = true |
619 | | -isless(::Tuple, ::Tuple{}) = false |
620 | | - |
621 | 628 | """ |
622 | 629 | isless(t1::Tuple, t2::Tuple) |
623 | 630 |
|
624 | 631 | Return `true` when `t1` is less than `t2` in lexicographic order. |
625 | 632 | """ |
626 | 633 | function isless(t1::Tuple, t2::Tuple) |
627 | | - a, b = t1[1], t2[1] |
628 | | - isless(a, b) || (isequal(a, b) && isless(tail(t1), tail(t2))) |
629 | | -end |
630 | | -function isless(t1::Any32, t2::Any32) |
631 | | - n1, n2 = length(t1), length(t2) |
632 | | - for i = 1:min(n1, n2) |
633 | | - a, b = t1[i], t2[i] |
634 | | - if !isequal(a, b) |
635 | | - return isless(a, b) |
| 634 | + f(::Tuple{}, ::Tuple{}) = false |
| 635 | + f(::Tuple{}, ::Tuple) = true |
| 636 | + f(::Tuple, ::Tuple{}) = false |
| 637 | + function f(t1::Tuple, t2::Tuple) |
| 638 | + a, b = t1[1], t2[1] |
| 639 | + isless(a, b) || (isequal(a, b) && isless(tail(t1), tail(t2))) |
| 640 | + end |
| 641 | + function f(t1::Any32, t2::Any32) |
| 642 | + n1, n2 = length(t1), length(t2) |
| 643 | + for i = 1:min(n1, n2) |
| 644 | + a, b = t1[i], t2[i] |
| 645 | + if !isequal(a, b) |
| 646 | + return isless(a, b) |
| 647 | + end |
636 | 648 | end |
| 649 | + return n1 < n2 |
637 | 650 | end |
638 | | - return n1 < n2 |
| 651 | + f(t1, t2) |
639 | 652 | end |
640 | 653 |
|
641 | 654 | ## functions ## |
642 | 655 |
|
643 | | -isempty(x::Tuple{}) = true |
644 | | -isempty(@nospecialize x::Tuple) = false |
| 656 | +function isempty(x::Tuple) |
| 657 | + f(x::Tuple{}) = true |
| 658 | + f(@nospecialize x::Tuple) = false |
| 659 | + f(x) |
| 660 | +end |
645 | 661 |
|
646 | 662 | revargs() = () |
647 | 663 | revargs(x, r...) = (revargs(r...)..., x) |
@@ -679,11 +695,14 @@ empty(@nospecialize x::Tuple) = () |
679 | 695 | foreach(f, itr::Tuple) = foldl((_, x) -> (f(x); nothing), itr, init=nothing) |
680 | 696 | foreach(f, itr::Tuple, itrs::Tuple...) = foldl((_, xs) -> (f(xs...); nothing), zip(itr, itrs...), init=nothing) |
681 | 697 |
|
682 | | -circshift((@nospecialize t::Union{Tuple{},Tuple{Any}}), @nospecialize _::Integer) = t |
683 | | -circshift(t::Tuple{Any,Any}, shift::Integer) = iseven(shift) ? t : reverse(t) |
684 | | -function circshift(x::Tuple{Any,Any,Any,Vararg{Any,N}}, shift::Integer) where {N} |
685 | | - @inline |
686 | | - len = N + 3 |
687 | | - j = mod1(shift, len) |
688 | | - ntuple(k -> getindex(x, k-j+ifelse(k>j,0,len)), Val(len))::Tuple |
| 698 | +function circshift(t::Tuple, shift::Integer) |
| 699 | + f((@nospecialize t::Union{Tuple{},Tuple{Any}}), @nospecialize _::Integer) = t |
| 700 | + f(t::Tuple{Any,Any}, shift::Integer) = iseven(shift) ? t : reverse(t) |
| 701 | + function f(x::Tuple{Any,Any,Any,Vararg{Any,N}}, shift::Integer) where {N} |
| 702 | + @inline |
| 703 | + len = N + 3 |
| 704 | + j = mod1(shift, len) |
| 705 | + ntuple(k -> getindex(x, k-j+ifelse(k>j,0,len)), Val(len))::Tuple |
| 706 | + end |
| 707 | + f(t, shift) |
689 | 708 | end |
0 commit comments