Skip to content

Commit

Permalink
Backports release 1.11 (#55936)
Browse files Browse the repository at this point in the history
Backported PRs:
- [x] #55849 <!-- Mmap: fix grow! for non file IOs -->
- [x] #55863 <!-- Update TaskLocalRNG docstring according to #49110 -->
- [x] #54433 <!-- Root globals in toplevel exprs -->
- [x] #55828 <!-- Fix some corner cases of `isapprox` with unsigned
integers -->
- [x] #55890 <!-- Profile: fix order of fields in heapsnapshot & improve
formatting -->
- [x] #55884 <!-- inference: add missing `TypeVar` handling for
`instanceof_tfunc` -->
- [x] #55881 <!-- Install terminfo data under /usr/share/julia -->
- [x] #55909 <!-- do not intentionally suppress errors in precompile
script from being reported or failing the result -->
- [x] #55355 <!-- relocation: account for trailing path separator in
depot paths -->
- [x] #55917 <!-- fix rawbigints OOB issues -->
- [x] #55892 <!-- TOML: Avoid type-pirating `Base.TOML.Parser` -->
- [x] #55798 <!-- Broadcast binary ops involving strided triangular -->
- [x] #55919 <!-- Limit `@inbounds` to indexing in the dual-iterator
branch in `copyto_unaliased!` -->

Contains multiple commits, manual intervention needed:
- [ ] #54009 <!-- allow extensions to trigger from packages in [deps]
-->
- [ ] #55509 <!-- Fix cong implementation to be properly random and not
just cycling. -->
- [ ] #55569 <!-- Add a docs section about loading/precomp/ttfx time
tuning -->
- [ ] #55824 <!-- Replace regex package module checks with actual code
checks -->

Non-merged PRs with backport label:
- [ ] #55932 <!-- REPL: make UndefVarError aware of imported modules -->
- [ ] #55910 <!-- Prevent extensions from blocking parallel
pre-compilation -->
- [ ] #55908 <!-- add logic to prefer loading modules that are already
loaded -->
- [ ] #55886 <!-- irrationals: restrict assume effects annotations to
known types -->
- [ ] #55871 <!-- lowering: don't reverse handler order in
`(pop-handler-list ...)` -->
- [ ] #55870 <!-- fix infinite recursion in `promote_type` for
`Irrational` -->
- [ ] #55867 <!-- update `hash` doc string: `widen` not required any
more -->
- [ ] #55851 <!-- [REPL] Fix #55850 by using `safe_realpath` instead of
`abspath` in `projname` -->
- [ ] #55813 <!-- Check for conflicting `@ccallable` name before JIT
registration -->
- [ ] #55743 <!-- doc: heap snapshot viewing -->
- [ ] #55741 <!-- Change annotations to use a NamedTuple -->
- [ ] #55534 <!-- Set stdlib sources as read-only during installation
-->
- [ ] #55499 <!-- propagate the terminal's `displaysize` to the
`IOContext` used by the REPL -->
- [ ] #55458 <!-- Allow for generically extracting unannotated string
-->
- [ ] #55457 <!-- Make AnnotateChar equality consider annotations -->
- [ ] #55220 <!-- `isfile_casesensitive` fixes on Windows -->
- [ ] #55169 <!-- `propertynames` for SVD respects private argument -->
- [ ] #54457 <!-- Make `String(::Memory)` copy -->
- [ ] #53957 <!-- tweak how filtering is done for what packages should
be precompiled -->
- [ ] #51479 <!-- prevent code loading from lookin in the versioned
environment when building Julia -->
- [ ] #50813 <!-- More doctests for Sockets and capitalization fix -->
- [ ] #50157 <!-- improve docs for `@inbounds` and
`Base.@propagate_inbounds` -->
  • Loading branch information
KristofferC authored Oct 1, 2024
2 parents b4b9add + cb5cd2a commit 4c87cb4
Show file tree
Hide file tree
Showing 30 changed files with 330 additions and 118 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ endif
$(INSTALL_F) $(JULIAHOME)/contrib/julia.appdata.xml $(DESTDIR)$(datarootdir)/appdata/
# Install terminal info database
ifneq ($(WITH_TERMINFO),0)
cp -R -L $(build_datarootdir)/terminfo $(DESTDIR)$(datarootdir)
cp -R -L $(build_datarootdir)/julia/terminfo $(DESTDIR)$(datarootdir)/julia/
endif

# Update RPATH entries and JL_SYSTEM_IMAGE_PATH if $(private_libdir_rel) != $(build_private_libdir_rel)
Expand Down
7 changes: 2 additions & 5 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1096,11 +1096,8 @@ function copyto_unaliased!(deststyle::IndexStyle, dest::AbstractArray, srcstyle:
end
else
# Dual-iterator implementation
ret = iterate(iterdest)
@inbounds for a in src
idx, state = ret::NTuple{2,Any}
dest[idx] = a
ret = iterate(iterdest, state)
for (Idest, Isrc) in zip(iterdest, itersrc)
@inbounds dest[Idest] = src[Isrc]
end
end
end
Expand Down
8 changes: 4 additions & 4 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ function instanceof_tfunc(@nospecialize(t), astag::Bool=false, @nospecialize(tro
end
return tr, isexact, isconcrete, istype
elseif isa(t, Union)
ta, isexact_a, isconcrete_a, istype_a = instanceof_tfunc(t.a, astag, troot)
tb, isexact_b, isconcrete_b, istype_b = instanceof_tfunc(t.b, astag, troot)
ta, isexact_a, isconcrete_a, istype_a = instanceof_tfunc(unwraptv(t.a), astag, troot)
tb, isexact_b, isconcrete_b, istype_b = instanceof_tfunc(unwraptv(t.b), astag, troot)
isconcrete = isconcrete_a && isconcrete_b
istype = istype_a && istype_b
# most users already handle the Union case, so here we assume that
Expand Down Expand Up @@ -549,9 +549,9 @@ add_tfunc(Core.sizeof, 1, 1, sizeof_tfunc, 1)
end
end
if isa(x, Union)
na = nfields_tfunc(𝕃, x.a)
na = nfields_tfunc(𝕃, unwraptv(x.a))
na === Int && return Int
return tmerge(na, nfields_tfunc(𝕃, x.b))
return tmerge(𝕃, na, nfields_tfunc(𝕃, unwraptv(x.b)))
end
return Int
end
Expand Down
4 changes: 3 additions & 1 deletion base/floatfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,9 @@ function isapprox(x::Integer, y::Integer;
if norm === abs && atol < 1 && rtol == 0
return x == y
else
return norm(x - y) <= max(atol, rtol*max(norm(x), norm(y)))
# We need to take the difference `max` - `min` when comparing unsigned integers.
_x, _y = x < y ? (x, y) : (y, x)
return norm(_y - _x) <= max(atol, rtol*max(norm(_x), norm(_y)))
end
end

Expand Down
26 changes: 16 additions & 10 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3119,23 +3119,29 @@ mutable struct CacheHeaderIncludes
const modpath::Vector{String} # seemingly not needed in Base, but used by Revise
end

function replace_depot_path(path::AbstractString)
for depot in DEPOT_PATH
!isdir(depot) && continue

# Strip extraneous pathseps through normalization.
if isdirpath(depot)
depot = dirname(depot)
end

if startswith(path, depot)
function replace_depot_path(path::AbstractString, depots::Vector{String}=normalize_depots_for_relocation())
for depot in depots
if startswith(path, string(depot, Filesystem.pathsep())) || path == depot
path = replace(path, depot => "@depot"; count=1)
break
end
end
return path
end

function normalize_depots_for_relocation()
depots = String[]
sizehint!(depots, length(DEPOT_PATH))
for d in DEPOT_PATH
isdir(d) || continue
if isdirpath(d)
d = dirname(d)
end
push!(depots, abspath(d))
end
return depots
end

function restore_depot_path(path::AbstractString, depot::AbstractString)
replace(path, r"^@depot" => depot; count=1)
end
Expand Down
31 changes: 22 additions & 9 deletions base/rawbigints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,21 @@ reversed_index(n::Int, i::Int) = n - i - 1
reversed_index(x, i::Int, v::Val) = reversed_index(elem_count(x, v), i)::Int
split_bit_index(x::RawBigInt, i::Int) = divrem(i, word_length(x), RoundToZero)

function get_elem_words_raw(x::RawBigInt{T}, i::Int) where {T}
@boundscheck if (i < 0) || (elem_count(x, Val(:words)) i)
throw(BoundsError(x, i))
end
d = x.d
j = i + 1
(GC.@preserve d unsafe_load(Ptr{T}(pointer(d)), j))::T
end

"""
`i` is the zero-based index of the wanted word in `x`, starting from
the less significant words.
"""
function get_elem(x::RawBigInt{T}, i::Int, ::Val{:words}, ::Val{:ascending}) where {T}
# `i` must be non-negative and less than `x.word_count`
d = x.d
(GC.@preserve d unsafe_load(Ptr{T}(pointer(d)), i + 1))::T
function get_elem(x::RawBigInt, i::Int, ::Val{:words}, ::Val{:ascending})
@inbounds @inline get_elem_words_raw(x, i)
end

function get_elem(x, i::Int, v::Val, ::Val{:descending})
Expand Down Expand Up @@ -96,25 +103,31 @@ end

"""
Returns an integer of type `R`, consisting of the `len` most
significant bits of `x`.
significant bits of `x`. If there are less than `len` bits in `x`,
the least significant bits are zeroed.
"""
function truncated(::Type{R}, x::RawBigInt, len::Int) where {R<:Integer}
ret = zero(R)
if 0 < len
word_count, bit_count_in_word = split_bit_index(x, len)
k = word_length(x)
vals = (Val(:words), Val(:descending))
lenx = elem_count(x, first(vals))

for w 0:(word_count - 1)
ret <<= k
word = get_elem(x, w, vals...)
ret |= R(word)
if w < lenx
word = get_elem(x, w, vals...)
ret |= R(word)
end
end

if !iszero(bit_count_in_word)
ret <<= bit_count_in_word
wrd = get_elem(x, word_count, vals...)
ret |= R(wrd >>> (k - bit_count_in_word))
if word_count < lenx
wrd = get_elem(x, word_count, vals...)
ret |= R(wrd >>> (k - bit_count_in_word))
end
end
end
ret::R
Expand Down
2 changes: 1 addition & 1 deletion base/terminfo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ function find_terminfo_file(term::String)
append!(terminfo_dirs,
replace(split(ENV["TERMINFO_DIRS"], ':'),
"" => "/usr/share/terminfo"))
push!(terminfo_dirs, normpath(Sys.BINDIR, DATAROOTDIR, "terminfo"))
push!(terminfo_dirs, normpath(Sys.BINDIR, DATAROOTDIR, "julia", "terminfo"))
Sys.isunix() &&
push!(terminfo_dirs, "/etc/terminfo", "/lib/terminfo", "/usr/share/terminfo")
for dir in terminfo_dirs
Expand Down
7 changes: 3 additions & 4 deletions contrib/generate_precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,7 @@ generate_precompile_statements() = try # Make sure `ansi_enablecursor` is printe
print_state("step1" => "F$n_step1")
return :ok
end
Base.errormonitor(step1)
!PARALLEL_PRECOMPILATION && wait(step1)
PARALLEL_PRECOMPILATION ? bind(statements_step1, step1) : wait(step1)

# Create a staging area where all the loaded packages are available
PrecompileStagingArea = Module()
Expand All @@ -357,7 +356,7 @@ generate_precompile_statements() = try # Make sure `ansi_enablecursor` is printe
# Make statements unique
statements = Set{String}()
# Execute the precompile statements
for sts in [statements_step1,], statement in sts
for statement in statements_step1
# Main should be completely clean
occursin("Main.", statement) && continue
Base.in!(statement, statements) && continue
Expand Down Expand Up @@ -393,6 +392,7 @@ generate_precompile_statements() = try # Make sure `ansi_enablecursor` is printe
println()
# Seems like a reasonable number right now, adjust as needed
# comment out if debugging script
have_repl = false
n_succeeded > (have_repl ? 650 : 90) || @warn "Only $n_succeeded precompile statements"

fetch(step1) == :ok || throw("Step 1 of collecting precompiles failed.")
Expand All @@ -403,7 +403,6 @@ generate_precompile_statements() = try # Make sure `ansi_enablecursor` is printe
finally
fancyprint && print(ansi_enablecursor)
GC.gc(true); GC.gc(false); # reduce memory footprint
return
end

generate_precompile_statements()
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
83f567b5c65ae36ebd9b5878cf009513
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bc1e6de2c679b862caeb5c1fb6c3187c9da4dc2e37dc89b5cdf1498c5a26fbe7516773b53c039927abd89a1a9e8215f410b08a3da9d1b6489fe9ca2da60e57d2
4 changes: 2 additions & 2 deletions deps/terminfo.mk
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ $(BUILDDIR)/TermInfoDB-v$(TERMINFO_VER)/build-checked: $(BUILDDIR)/TermInfoDB-v$
echo 1 > $@

define TERMINFO_INSTALL
mkdir -p $2/$$(build_datarootdir)
cp -R $1/terminfo $2/$$(build_datarootdir)
mkdir -p $2/$$(build_datarootdir)/julia
cp -R $1/terminfo $2/$$(build_datarootdir)/julia/
endef
$(eval $(call staged-install, \
terminfo,TermInfoDB-v$(TERMINFO_VER), \
Expand Down
5 changes: 3 additions & 2 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6144,8 +6144,9 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaidx_
jl_value_t *val = expr;
if (jl_is_quotenode(expr))
val = jl_fieldref_noalloc(expr, 0);
if (jl_is_method(ctx.linfo->def.method)) // toplevel exprs are already rooted
val = jl_ensure_rooted(ctx, val);
// Toplevel exprs are rooted but because codegen assumes this is constant, it removes the write barriers for this code.
// This means we have to globally root the value here. (The other option would be to change how we optimize toplevel code)
val = jl_ensure_rooted(ctx, val);
return mark_julia_const(ctx, val);
}

Expand Down
42 changes: 18 additions & 24 deletions src/gc-heap-snapshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -607,38 +607,32 @@ void final_serialize_heap_snapshot(ios_t *json, ios_t *strings, HeapSnapshot &sn
{
// mimicking https://github.com/nodejs/node/blob/5fd7a72e1c4fbaf37d3723c4c81dce35c149dc84/deps/v8/src/profiler/heap-snapshot-generator.cc#L2567-L2567
// also https://github.com/microsoft/vscode-v8-heap-tools/blob/c5b34396392397925ecbb4ecb904a27a2754f2c1/v8-heap-parser/src/decoder.rs#L43-L51
ios_printf(json, "{\"snapshot\":{");
ios_printf(json, "{\"snapshot\":{\n");

ios_printf(json, "\"meta\":{");
ios_printf(json, "\"node_fields\":[\"type\",\"name\",\"id\",\"self_size\",\"edge_count\",\"trace_node_id\",\"detachedness\"],");
ios_printf(json, "\"node_types\":[");
ios_printf(json, " \"meta\":{\n");
ios_printf(json, " \"node_fields\":[\"type\",\"name\",\"id\",\"self_size\",\"edge_count\",\"trace_node_id\",\"detachedness\"],\n");
ios_printf(json, " \"node_types\":[");
snapshot.node_types.print_json_array(json, false);
ios_printf(json, ",");
ios_printf(json, "\"string\", \"number\", \"number\", \"number\", \"number\", \"number\"],");
ios_printf(json, "\"edge_fields\":[\"type\",\"name_or_index\",\"to_node\"],");
ios_printf(json, "\"edge_types\":[");
ios_printf(json, "\"string\", \"number\", \"number\", \"number\", \"number\", \"number\"],\n");
ios_printf(json, " \"edge_fields\":[\"type\",\"name_or_index\",\"to_node\"],\n");
ios_printf(json, " \"edge_types\":[");
snapshot.edge_types.print_json_array(json, false);
ios_printf(json, ",");
ios_printf(json, "\"string_or_number\",\"from_node\"],");
ios_printf(json, "\"string_or_number\",\"from_node\"],\n");
// not used. Required by microsoft/vscode-v8-heap-tools
ios_printf(json, "\"trace_function_info_fields\":[\"function_id\",\"name\",\"script_name\",\"script_id\",\"line\",\"column\"],");
ios_printf(json, "\"trace_node_fields\":[\"id\",\"function_info_index\",\"count\",\"size\",\"children\"],");
ios_printf(json, "\"sample_fields\":[\"timestamp_us\",\"last_assigned_id\"],");
ios_printf(json, "\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]");
ios_printf(json, " \"trace_function_info_fields\":[\"function_id\",\"name\",\"script_name\",\"script_id\",\"line\",\"column\"],\n");
ios_printf(json, " \"trace_node_fields\":[\"id\",\"function_info_index\",\"count\",\"size\",\"children\"],\n");
ios_printf(json, " \"sample_fields\":[\"timestamp_us\",\"last_assigned_id\"],\n");
ios_printf(json, " \"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]\n");
// end not used
ios_printf(json, "},\n"); // end "meta"
ios_printf(json, " },\n"); // end "meta"

ios_printf(json, "\"node_count\":%zu,", snapshot.num_nodes);
ios_printf(json, "\"edge_count\":%zu,", snapshot.num_edges);
ios_printf(json, "\"trace_function_count\":0"); // not used. Required by microsoft/vscode-v8-heap-tools
ios_printf(json, "},\n"); // end "snapshot"

// not used. Required by microsoft/vscode-v8-heap-tools
ios_printf(json, "\"trace_function_infos\":[],");
ios_printf(json, "\"trace_tree\":[],");
ios_printf(json, "\"samples\":[],");
ios_printf(json, "\"locations\":[]");
// end not used
ios_printf(json, " \"node_count\":%zu,\n", snapshot.num_nodes);
ios_printf(json, " \"edge_count\":%zu,\n", snapshot.num_edges);
ios_printf(json, " \"trace_function_count\":0\n"); // not used. Required by microsoft/vscode-v8-heap-tools
ios_printf(json, "}\n"); // end "snapshot"

// this } is removed by the julia reassembler in Profile
ios_printf(json, "}");
}
17 changes: 13 additions & 4 deletions src/precompile.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,17 @@ void write_srctext(ios_t *f, jl_array_t *udeps, int64_t srctextpos) {
static jl_value_t *replace_depot_func = NULL;
if (!replace_depot_func)
replace_depot_func = jl_get_global(jl_base_module, jl_symbol("replace_depot_path"));
static jl_value_t *normalize_depots_func = NULL;
if (!normalize_depots_func)
normalize_depots_func = jl_get_global(jl_base_module, jl_symbol("normalize_depots_for_relocation"));
ios_t srctext;
jl_value_t *deptuple = NULL;
JL_GC_PUSH2(&deptuple, &udeps);
jl_value_t *deptuple = NULL, *depots = NULL;
JL_GC_PUSH3(&deptuple, &udeps, &depots);
jl_task_t *ct = jl_current_task;
size_t last_age = ct->world_age;
ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
depots = jl_apply(&normalize_depots_func, 1);
ct->world_age = last_age;
for (size_t i = 0; i < len; i++) {
deptuple = jl_array_ptr_ref(udeps, i);
jl_value_t *depmod = jl_fieldref(deptuple, 0); // module
Expand All @@ -60,13 +68,14 @@ void write_srctext(ios_t *f, jl_array_t *udeps, int64_t srctextpos) {
}

jl_value_t **replace_depot_args;
JL_GC_PUSHARGS(replace_depot_args, 2);
JL_GC_PUSHARGS(replace_depot_args, 3);
replace_depot_args[0] = replace_depot_func;
replace_depot_args[1] = abspath;
replace_depot_args[2] = depots;
jl_task_t *ct = jl_current_task;
size_t last_age = ct->world_age;
ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
jl_value_t *depalias = (jl_value_t*)jl_apply(replace_depot_args, 2);
jl_value_t *depalias = (jl_value_t*)jl_apply(replace_depot_args, 3);
ct->world_age = last_age;
JL_GC_POP();

Expand Down
20 changes: 14 additions & 6 deletions src/staticdata_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,16 @@ static int64_t write_dependency_list(ios_t *s, jl_array_t* worklist, jl_array_t
static jl_value_t *replace_depot_func = NULL;
if (!replace_depot_func)
replace_depot_func = jl_get_global(jl_base_module, jl_symbol("replace_depot_path"));
static jl_value_t *normalize_depots_func = NULL;
if (!normalize_depots_func)
normalize_depots_func = jl_get_global(jl_base_module, jl_symbol("normalize_depots_for_relocation"));

jl_value_t *depots = NULL, *prefs_hash = NULL, *prefs_list = NULL;
JL_GC_PUSH2(&depots, &prefs_list);
last_age = ct->world_age;
ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
depots = jl_apply(&normalize_depots_func, 1);
ct->world_age = last_age;

// write a placeholder for total size so that we can quickly seek past all of the
// dependencies if we don't need them
Expand All @@ -764,13 +774,14 @@ static int64_t write_dependency_list(ios_t *s, jl_array_t* worklist, jl_array_t

if (replace_depot_func) {
jl_value_t **replace_depot_args;
JL_GC_PUSHARGS(replace_depot_args, 2);
JL_GC_PUSHARGS(replace_depot_args, 3);
replace_depot_args[0] = replace_depot_func;
replace_depot_args[1] = deppath;
replace_depot_args[2] = depots;
ct = jl_current_task;
size_t last_age = ct->world_age;
ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
deppath = (jl_value_t*)jl_apply(replace_depot_args, 2);
deppath = (jl_value_t*)jl_apply(replace_depot_args, 3);
ct->world_age = last_age;
JL_GC_POP();
}
Expand Down Expand Up @@ -803,9 +814,6 @@ static int64_t write_dependency_list(ios_t *s, jl_array_t* worklist, jl_array_t
write_int32(s, 0); // terminator, for ease of reading

// Calculate Preferences hash for current package.
jl_value_t *prefs_hash = NULL;
jl_value_t *prefs_list = NULL;
JL_GC_PUSH1(&prefs_list);
if (jl_base_module) {
// Toplevel module is the module we're currently compiling, use it to get our preferences hash
jl_value_t * toplevel = (jl_value_t*)jl_get_global(jl_base_module, jl_symbol("__toplevel__"));
Expand Down Expand Up @@ -852,7 +860,7 @@ static int64_t write_dependency_list(ios_t *s, jl_array_t* worklist, jl_array_t
write_int32(s, 0);
write_uint64(s, 0);
}
JL_GC_POP(); // for prefs_list
JL_GC_POP(); // for depots, prefs_list

// write a dummy file position to indicate the beginning of the source-text
pos = ios_pos(s);
Expand Down
8 changes: 4 additions & 4 deletions stdlib/LinearAlgebra/src/symmetric.jl
Original file line number Diff line number Diff line change
Expand Up @@ -536,10 +536,10 @@ for f in (:+, :-)
@eval begin
$f(A::Hermitian, B::Symmetric{<:Real}) = $f(A, Hermitian(parent(B), sym_uplo(B.uplo)))
$f(A::Symmetric{<:Real}, B::Hermitian) = $f(Hermitian(parent(A), sym_uplo(A.uplo)), B)
$f(A::SymTridiagonal, B::Symmetric) = Symmetric($f(A, B.data), sym_uplo(B.uplo))
$f(A::Symmetric, B::SymTridiagonal) = Symmetric($f(A.data, B), sym_uplo(A.uplo))
$f(A::SymTridiagonal{<:Real}, B::Hermitian) = Hermitian($f(A, B.data), sym_uplo(B.uplo))
$f(A::Hermitian, B::SymTridiagonal{<:Real}) = Hermitian($f(A.data, B), sym_uplo(A.uplo))
$f(A::SymTridiagonal, B::Symmetric) = $f(Symmetric(A, sym_uplo(B.uplo)), B)
$f(A::Symmetric, B::SymTridiagonal) = $f(A, Symmetric(B, sym_uplo(A.uplo)))
$f(A::SymTridiagonal{<:Real}, B::Hermitian) = $f(Hermitian(A, sym_uplo(B.uplo)), B)
$f(A::Hermitian, B::SymTridiagonal{<:Real}) = $f(A, Hermitian(B, sym_uplo(A.uplo)))
end
end

Expand Down
Loading

0 comments on commit 4c87cb4

Please sign in to comment.