Less restrictive copyto! signature for triangular matrices (#54649)
On nightly, `copyto!(A::T, B::T) where {T<:UpperTriangular}` checks for
the types to be identical. This is overly restrictive, as we only need
to check that they are both `UpperTriangular`. This PR relaxes this,
which provides a significant performance boost for mismatched types.
```julia
julia> using LinearAlgebra
julia> A = UpperTriangular(rand(200,200)); B = UpperTriangular(view(rand(200,200),:,:));
julia> @btime copyto!($A, $B);
44.878 μs (0 allocations: 0 bytes) # nightly v"1.12.0-DEV.641"
5.658 μs (0 allocations: 0 bytes) # this PR
```
This PR also changes the behavior when the source and the destination
don't have the same size, in which case, `copyto!` should carry out a
linear copy and not a Cartesian one, as per its docstring. The previous
behavior may be obtained by calling
```julia
copyto!(A, CartesianIndices(B), B, CartesianIndices(B))
```
This change would mean that certain operations that used to work would
error now, e.g.:
```julia
julia> A = UpperTriangular(zeros(3,3)); B = UpperTriangular(rand(2,2));
julia> copyto!(A, B)
ERROR: ArgumentError: cannot set index in the upper triangular part (3, 1) of an UpperTriangular matrix to a nonzero value (0.6898709830945821)
```
whereas this used to carry out a Cartesian copy previously.
---------
Co-authored-by: Dilum Aluthge <dilum@aluthge.com>