Skip to content

Commit

Permalink
Merge branch 'master' into ah/EmptyDatesNow
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Sep 21, 2017
2 parents 4825913 + 896d599 commit d85c4d5
Show file tree
Hide file tree
Showing 81 changed files with 1,992 additions and 1,244 deletions.
15 changes: 15 additions & 0 deletions NEWS.md
Expand Up @@ -11,6 +11,11 @@ New language features
a function argument name, the argument is unpacked into local variables `x` and `y`
as in the assignment `(x, y) = arg` ([#6614]).

* Custom infix operators can now be defined by appending Unicode
combining marks, primes, and sub/superscripts to other operators.
For example, `+̂ₐ″` is parsed as an infix operator with the same
precedence as `+` ([#22089]).

Language changes
----------------

Expand Down Expand Up @@ -100,6 +105,9 @@ Breaking changes

This section lists changes that do not have deprecation warnings.

* `getindex(s::String, r::UnitRange{Int})` now throws `UnicodeError` if `last(r)`
is not a valid index into `s` ([#22572]).

* `ntuple(f, n::Integer)` throws `ArgumentError` if `n` is negative.
Previously an empty tuple was returned ([#21697]).

Expand Down Expand Up @@ -205,6 +213,10 @@ This section lists changes that do not have deprecation warnings.
* The `openspecfun` library is no longer built and shipped with Julia, as it is no longer
used internally ([#22390]).

* All loaded packges used to have bindings in `Main` (e.g. `Main.Package`). This is no
longer the case; now bindings will only exist for packages brought into scope by
typing `using Package` or `import Package` ([#17997]).

* `slicedim(b::BitVector, 1, x)` now consistently returns the same thing that `b[x]` would,
consistent with its documentation. Previously it would return a `BitArray{0}` for scalar
`x` ([#20233]).
Expand Down Expand Up @@ -456,6 +468,9 @@ Deprecated or removed
* `DateTime()`, `Date()`, and `Time()` have been deprecated, instead use `DateTime(1)`, `Date(1)`
and `Time(0)` respectively ([#23724]).

* The timing functions `tic`, `toc`, and `toq` are deprecated in favor of `@time` and `@elapsed`
([#17046]).

Command-line option changes
---------------------------

Expand Down
2 changes: 1 addition & 1 deletion base/dates/io.jl
Expand Up @@ -330,7 +330,7 @@ function DateFormat(f::AbstractString, locale::DateLocale=ENGLISH)

letters = String(collect(keys(CONVERSION_SPECIFIERS)))
for m in eachmatch(Regex("(?<!\\\\)([\\Q$letters\\E])\\1*"), f)
tran = replace(f[prev_offset:m.offset - 1], r"\\(.)", s"\1")
tran = replace(f[prev_offset:prevind(f, m.offset)], r"\\(.)", s"\1")

if !isempty(prev)
letter, width = prev
Expand Down
31 changes: 31 additions & 0 deletions base/deprecated.jl
Expand Up @@ -1822,6 +1822,37 @@ end
Base.@deprecate Time() Time(0)
end

export tic, toq, toc
function tic()
depwarn("tic() is deprecated, use @time, @elapsed, or calls to time_ns() instead.", :tic)
t0 = time_ns()
task_local_storage(:TIMERS, (t0, get(task_local_storage(), :TIMERS, ())))
return t0
end

function _toq()
t1 = time_ns()
timers = get(task_local_storage(), :TIMERS, ())
if timers === ()
error("toc() without tic()")
end
t0 = timers[1]::UInt64
task_local_storage(:TIMERS, timers[2])
(t1-t0)/1e9
end

function toq()
depwarn("toq() is deprecated, use @elapsed or calls to time_ns() instead.", :toq)
return _toq()
end

function toc()
depwarn("toc() is deprecated, use @time, @elapsed, or calls to time_ns() instead.", :toc)
t = _toq()
println("elapsed time: ", t, " seconds")
return t
end

@noinline function getaddrinfo(callback::Function, host::AbstractString)
depwarn("getaddrinfo with a callback function is deprecated, wrap code in @async instead for deferred execution", :getaddrinfo)
@async begin
Expand Down
3 changes: 0 additions & 3 deletions base/exports.jl
Expand Up @@ -897,11 +897,8 @@ export

# time
sleep,
tic,
time,
time_ns,
toc,
toq,

# dates
Date,
Expand Down
42 changes: 22 additions & 20 deletions base/interactiveutil.jl
Expand Up @@ -374,15 +374,15 @@ function code_warntype(io::IO, f, @nospecialize(t))
slotnames = sourceinfo_slotnames(src)
used_slotids = slots_used(src, slotnames)
for i = 1:length(slotnames)
print(emph_io, " ", slotnames[i])
if used_slotids[i]
print(emph_io, " ", slotnames[i])
if isa(src.slottypes, Array)
show_expr_type(emph_io, src.slottypes[i], true)
end
else
print(emph_io, " <optimized out>")
print(emph_io, '\n')
elseif !('#' in slotnames[i] || '@' in slotnames[i])
print(emph_io, " ", slotnames[i], "<optimized out>\n")
end
print(emph_io, '\n')
end
print(emph_io, "\nBody:\n ")
body = Expr(:body)
Expand Down Expand Up @@ -566,7 +566,7 @@ end
Return an array of methods with an argument of type `typ`.
The optional second argument restricts the search to a particular module or function
(the default is all modules, starting from Main).
(the default is all top-level modules).
If optional `showparents` is `true`, also return arguments with a parent type of `typ`,
excluding type `Any`.
Expand All @@ -588,7 +588,7 @@ function methodswith(t::Type, f::Function, showparents::Bool=false, meths = Meth
return meths
end

function methodswith(t::Type, m::Module, showparents::Bool=false)
function _methodswith(t::Type, m::Module, showparents::Bool)
meths = Method[]
for nm in names(m)
if isdefined(m, nm)
Expand All @@ -601,17 +601,12 @@ function methodswith(t::Type, m::Module, showparents::Bool=false)
return unique(meths)
end

methodswith(t::Type, m::Module, showparents::Bool=false) = _methodswith(t, m, showparents)

function methodswith(t::Type, showparents::Bool=false)
meths = Method[]
mainmod = Main
# find modules in Main
for nm in names(mainmod)
if isdefined(mainmod, nm)
mod = getfield(mainmod, nm)
if isa(mod, Module)
append!(meths, methodswith(t, mod, showparents))
end
end
for mod in loaded_modules_array()
append!(meths, _methodswith(t, mod, showparents))
end
return unique(meths)
end
Expand Down Expand Up @@ -678,8 +673,10 @@ download(url, filename)
workspace()
Replace the top-level module (`Main`) with a new one, providing a clean workspace. The
previous `Main` module is made available as `LastMain`. A previously-loaded package can be
accessed using a statement such as `using LastMain.Package`.
previous `Main` module is made available as `LastMain`.
If `Package` was previously loaded, `using Package` in the new `Main` will re-use the
loaded copy. Run `reload("Package")` first to load a fresh copy.
This function should only be used interactively.
"""
Expand All @@ -700,15 +697,20 @@ end
# testing

"""
runtests([tests=["all"] [, numcores=ceil(Int, Sys.CPU_CORES / 2) ]])
Base.runtests(tests=["all"], numcores=ceil(Int, Sys.CPU_CORES / 2);
exit_on_error=false)
Run the Julia unit tests listed in `tests`, which can be either a string or an array of
strings, using `numcores` processors. (not exported)
strings, using `numcores` processors. If `exit_on_error` is `false`, when one test
fails, all remaining tests in other files will still be run; they are otherwise discarded,
when `exit_on_error == true`.
"""
function runtests(tests = ["all"], numcores = ceil(Int, Sys.CPU_CORES / 2))
function runtests(tests = ["all"], numcores = ceil(Int, Sys.CPU_CORES / 2);
exit_on_error=false)
if isa(tests,AbstractString)
tests = split(tests)
end
exit_on_error && push!(tests, "--exit-on-error")
ENV2 = copy(ENV)
ENV2["JULIA_CPU_CORES"] = "$numcores"
try
Expand Down
15 changes: 11 additions & 4 deletions base/linalg/dense.jl
Expand Up @@ -462,12 +462,17 @@ julia> exp(A)
```
"""
exp(A::StridedMatrix{<:BlasFloat}) = exp!(copy(A))
exp(A::StridedMatrix{<:Integer}) = exp!(float(A))
exp(A::StridedMatrix{<:Union{Integer,Complex{<:Integer}}}) = exp!(float.(A))

## Destructive matrix exponential using algorithm from Higham, 2008,
## "Functions of Matrices: Theory and Computation", SIAM
function exp!(A::StridedMatrix{T}) where T<:BlasFloat
n = checksquare(A)
if T <: Real
if issymmetric(A)
return full(exp(Symmetric(A)))
end
end
if ishermitian(A)
return full(exp(Hermitian(A)))
end
Expand Down Expand Up @@ -592,11 +597,13 @@ julia> log(A)
"""
function log(A::StridedMatrix{T}) where T
# If possible, use diagonalization
if issymmetric(A) && T <: Real
return log(Symmetric(A))
if T <: Real
if issymmetric(A)
return full(log(Symmetric(A)))
end
end
if ishermitian(A)
return log(Hermitian(A))
return full(log(Hermitian(A)))
end

# Use Schur decomposition
Expand Down
6 changes: 3 additions & 3 deletions base/linalg/lapack.jl
Expand Up @@ -2600,13 +2600,13 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in
chkside(side)
chkstride1(A, C, tau)
m,n = ndims(C) == 2 ? size(C) : (size(C, 1), 1)
mA, nA = size(A)
nA = size(A, 2)
k = length(tau)
if side == 'L' && m != nA
throw(DimensionMismatch("for a left-sided multiplication, the first dimension of C, $m, must equal the second dimension of A, $nA"))
end
if side == 'R' && n != mA
throw(DimensionMismatch("for a right-sided multiplication, the second dimension of C, $n, must equal the first dimension of A, $mA"))
if side == 'R' && n != nA
throw(DimensionMismatch("for a right-sided multiplication, the second dimension of C, $n, must equal the second dimension of A, $nA"))
end
if side == 'L' && k > m
throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= m = $m"))
Expand Down
107 changes: 64 additions & 43 deletions base/linalg/lq.jl
Expand Up @@ -70,13 +70,8 @@ function getindex(A::LQ, d::Symbol)
end
end

function getindex(A::LQPackedQ, i::Integer, j::Integer)
x = zeros(eltype(A), size(A, 1))
x[i] = 1
y = zeros(eltype(A), size(A, 2))
y[j] = 1
return dot(x, A*y)
end
getindex(A::LQPackedQ, i::Integer, j::Integer) =
A_mul_B!(A, setindex!(zeros(eltype(A), size(A, 2)), 1, j))[i]

getq(A::LQ) = LQPackedQ(A.factors, A.τ)

Expand All @@ -97,17 +92,22 @@ full(Q::LQPackedQ; thin::Bool = true) =

size(A::LQ, dim::Integer) = size(A.factors, dim)
size(A::LQ) = size(A.factors)
function size(A::LQPackedQ, dim::Integer)
if 0 < dim && dim <= 2
return size(A.factors, dim)
elseif 0 < dim && dim > 2
return 1
else

# size(Q::LQPackedQ) yields the shape of Q's square form
function size(Q::LQPackedQ)
n = size(Q.factors, 2)
return n, n
end
function size(Q::LQPackedQ, dim::Integer)
if dim < 1
throw(BoundsError())
elseif dim <= 2 # && 1 <= dim
return size(Q.factors, 2)
else # 2 < dim
return 1
end
end

size(A::LQPackedQ) = size(A.factors)

## Multiplication by LQ
A_mul_B!(A::LQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} =
Expand Down Expand Up @@ -164,39 +164,60 @@ for (f1, f2) in ((:A_mul_Bc, :A_mul_B!),
end
end

### AQ
A_mul_B!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasFloat} = LAPACK.ormlq!('R', 'N', B.factors, B.τ, A)
function *(A::StridedMatrix{TA}, B::LQPackedQ{TB}) where {TA,TB}
TAB = promote_type(TA,TB)
if size(B.factors,2) == size(A,2)
A_mul_B!(copy_oftype(A, TAB),convert(AbstractMatrix{TAB},B))
elseif size(B.factors,1) == size(A,2)
A_mul_B!( [A zeros(TAB, size(A,1), size(B.factors,2)-size(B.factors,1))], convert(AbstractMatrix{TAB},B))
# in-place right-application of LQPackedQs
# these methods require that the applied-to matrix's (A's) number of columns
# match the number of columns (nQ) of the LQPackedQ (Q) (necessary for in-place
# operation, and the underlying LAPACK routine (ormlq) treats the implicit Q
# as its (nQ-by-nQ) square form)
A_mul_B!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasFloat} =
LAPACK.ormlq!('R', 'N', B.factors, B.τ, A)
A_mul_Bc!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasReal} =
LAPACK.ormlq!('R', 'T', B.factors, B.τ, A)
A_mul_Bc!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasComplex} =
LAPACK.ormlq!('R', 'C', B.factors, B.τ, A)

# out-of-place right-application of LQPackedQs
# unlike their in-place equivalents, these methods: (1) check whether the applied-to
# matrix's (A's) appropriate dimension (columns for A_*, rows for Ac_*) matches the
# number of columns (nQ) of the LQPackedQ (Q), as the underlying LAPACK routine (ormlq)
# treats the implicit Q as its (nQ-by-nQ) square form; and (2) if the preceding dimensions
# do not match, these methods check whether the appropriate dimension of A instead matches
# the number of rows of the matrix of which Q is a factor (i.e. size(Q.factors, 1)),
# and if so zero-extends A as necessary for check (1) to pass (if possible).
*(A::StridedVecOrMat, Q::LQPackedQ) = _A_mul_Bq(A_mul_B!, A, Q)
A_mul_Bc(A::StridedVecOrMat, Q::LQPackedQ) = _A_mul_Bq(A_mul_Bc!, A, Q)
function _A_mul_Bq(A_mul_Bop!::FT, A::StridedVecOrMat, Q::LQPackedQ) where FT<:Function
TR = promote_type(eltype(A), eltype(Q))
if size(A, 2) == size(Q.factors, 2)
C = copy_oftype(A, TR)
elseif size(A, 2) == size(Q.factors, 1)
C = zeros(TR, size(A, 1), size(Q.factors, 2))
copy!(C, 1, A, 1, length(A))
else
throw(DimensionMismatch("second dimension of A, $(size(A,2)), must equal one of the dimensions of B, $(size(B))"))
_rightappdimmismatch("columns")
end
end

### AQc
A_mul_Bc!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasReal} = LAPACK.ormlq!('R','T',B.factors,B.τ,A)
A_mul_Bc!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasComplex} = LAPACK.ormlq!('R','C',B.factors,B.τ,A)
function A_mul_Bc(A::StridedVecOrMat{TA}, B::LQPackedQ{TB}) where {TA<:Number,TB<:Number}
TAB = promote_type(TA,TB)
A_mul_Bc!(copy_oftype(A, TAB), convert(AbstractMatrix{TAB},(B)))
end

### AcQ/AcQc
for (f1, f2) in ((:Ac_mul_B, :A_mul_B!),
(:Ac_mul_Bc, :A_mul_Bc!))
@eval begin
function ($f1)(A::StridedMatrix, B::LQPackedQ)
TAB = promote_type(eltype(A), eltype(B))
AA = similar(A, TAB, (size(A, 2), size(A, 1)))
adjoint!(AA, A)
return ($f2)(AA, B)
end
return A_mul_Bop!(C, convert(AbstractMatrix{TR}, Q))
end
Ac_mul_B(A::StridedMatrix, Q::LQPackedQ) = _Ac_mul_Bq(A_mul_B!, A, Q)
Ac_mul_Bc(A::StridedMatrix, Q::LQPackedQ) = _Ac_mul_Bq(A_mul_Bc!, A, Q)
function _Ac_mul_Bq(A_mul_Bop!::FT, A::StridedMatrix, Q::LQPackedQ) where FT<:Function
TR = promote_type(eltype(A), eltype(Q))
if size(A, 1) == size(Q.factors, 2)
C = adjoint!(similar(A, TR, reverse(size(A))), A)
elseif size(A, 1) == size(Q.factors, 1)
C = zeros(TR, size(A, 2), size(Q.factors, 2))
adjoint!(view(C, :, 1:size(A, 1)), A)
else
_rightappdimmismatch("rows")
end
return A_mul_Bop!(C, convert(AbstractMatrix{TR}, Q))
end
_rightappdimmismatch(rowsorcols) =
throw(DimensionMismatch(string("the number of $(rowsorcols) of the matrix on the left ",
"must match either (1) the number of columns of the (LQPackedQ) matrix on the right ",
"or (2) the number of rows of that (LQPackedQ) matrix's internal representation ",
"(the factorization's originating matrix's number of rows)")))


function (\)(A::LQ{TA}, b::StridedVector{Tb}) where {TA,Tb}
S = promote_type(TA,Tb)
Expand Down
2 changes: 1 addition & 1 deletion base/linalg/lu.jl
Expand Up @@ -88,7 +88,7 @@ lufact(A::Union{AbstractMatrix{T}, AbstractMatrix{Complex{T}}},

# for all other types we must promote to a type which is stable under division
"""
lufact(A [,pivot=Val(true)]) -> F::LU
lufact(A, pivot=Val(true)) -> F::LU
Compute the LU factorization of `A`.
Expand Down

0 comments on commit d85c4d5

Please sign in to comment.