diff --git a/Makefile b/Makefile index dda792566108a1..90b566fc828ed0 100644 --- a/Makefile +++ b/Makefile @@ -186,6 +186,7 @@ $(build_private_libdir)/%.$(SHLIB_EXT): $(build_private_libdir)/%.o CORE_SRCS := $(addprefix $(JULIAHOME)/, \ base/boot.jl base/coreimg.jl \ + base/docs/core.jl \ base/abstractarray.jl \ base/array.jl \ base/bool.jl \ @@ -590,7 +591,7 @@ ifneq (,$(filter $(ARCH), i386 i486 i586 i686)) cd $(JULIAHOME)/dist-extras && \ $(JLDOWNLOAD) http://downloads.sourceforge.net/sevenzip/7z920.exe && \ 7z x -y 7z920.exe 7z.exe 7z.dll && \ - ../contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_42.2 \ + ../contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_Leap_42.2 \ "mingw32-libgfortran3 mingw32-libquadmath0 mingw32-libstdc++6 mingw32-libgcc_s_sjlj1 mingw32-libssp0 mingw32-libwinpthread1 mingw32-libexpat1 mingw32-zlib1" && \ cp usr/i686-w64-mingw32/sys-root/mingw/bin/*.dll . else ifeq ($(ARCH),x86_64) @@ -599,7 +600,7 @@ else ifeq ($(ARCH),x86_64) 7z x -y 7z920-x64.msi _7z.exe _7z.dll && \ mv _7z.dll 7z.dll && \ mv _7z.exe 7z.exe && \ - ../contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win64/openSUSE_42.2 \ + ../contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win64/openSUSE_Leap_42.2 \ "mingw64-libgfortran3 mingw64-libquadmath0 mingw64-libstdc++6 mingw64-libgcc_s_seh1 mingw64-libssp0 mingw64-libwinpthread1 mingw64-libexpat1 mingw64-zlib1" && \ cp usr/x86_64-w64-mingw32/sys-root/mingw/bin/*.dll . else diff --git a/NEWS.md b/NEWS.md index e272de5b9a2936..e7919a656cc3da 100644 --- a/NEWS.md +++ b/NEWS.md @@ -29,6 +29,16 @@ This section lists changes that do not have deprecation warnings. * `@__DIR__` returns the current working directory rather than `nothing` when not run from a file ([#21759]). + * `@__FILE__` and `@__DIR__` return information relative to the file that it was parsed from, + rather than from the task-local `SOURCE_PATH` global when it was expanded. + + * All macros receive an extra argument `__source__::LineNumberNode` which describes the + parser location in the source file for the `@` of the macro call. + It can be accessed as a normal argument variable in the body of the macro. + This is implemented by inserting an extra leading argument into the + `Expr(:macrocall, :@name, LineNumberNode(...), args...)` + surface syntax. ([#21746]) + * Passing the same keyword argument multiple times is now a syntax error ([#16937]). * `getsockname` on a `TCPSocket` now returns the locally bound address and port @@ -48,6 +58,9 @@ Library improvements method can be opened in an editor by entering the corresponding number in the REPL and pressing `^Q` ([#22007]). + * `getpeername` on a `TCPSocket` returns the address and port of the remote + endpoint of the TCP connection ([#21825]). + Compiler/Runtime improvements ----------------------------- diff --git a/README.windows.md b/README.windows.md index 96ccc1a7f9f17c..15278e2802f989 100644 --- a/README.windows.md +++ b/README.windows.md @@ -184,6 +184,12 @@ versions of the MinGW-w64 compilers available through Cygwin's package manager. either 32 or 64 bit Julia from either 32 or 64 bit Cygwin. 64 bit Cygwin has a slightly smaller but often more up-to-date selection of packages. + Advanced: you may skip steps 2-4 by running: + + setup-x86_64.exe -s -q -P cmake,gcc-g++,git,make,patch,curl,m4,python,p7zip,mingw64-i686-gcc-g++,mingw64-i686-gcc-fortran,mingw64-x86_64-gcc-g++,mingw64-x86_64-gcc-fortran + :: replace with a site from https://cygwin.com/mirrors.html + :: or run setup manually first and select a mirror + 2. Select installation location and download mirror. 3. At the '*Select Packages'* step, select the following: @@ -207,7 +213,7 @@ versions of the MinGW-w64 compilers available through Cygwin's package manager. 1. Get the Julia sources ```sh - git clone --recursive https://github.com/JuliaLang/julia.git + git clone https://github.com/JuliaLang/julia.git cd julia ``` Tip: If you get an `error: cannot fork() for fetch-pack: Resource @@ -219,7 +225,7 @@ versions of the MinGW-w64 compilers available through Cygwin's package manager. ```sh echo 'XC_HOST = i686-w64-mingw32' > Make.user # for 32 bit Julia # or - echo 'XC_HOST = x86_64-w64-mingw32' > Make.user #for 64 bit Julia + echo 'XC_HOST = x86_64-w64-mingw32' > Make.user # for 64 bit Julia ``` 3. Start the build @@ -227,6 +233,20 @@ versions of the MinGW-w64 compilers available through Cygwin's package manager. make -j 4 # Adjust the number of cores (4) to match your build environment. ``` + + > Protip: build both! + > ```sh + > make O=julia-win32 configure + > make O=julia-win64 configure + > echo 'XC_HOST = i686-w64-mingw32' > julia-win32/Make.user + > echo 'XC_HOST = x86_64-w64-mingw32' > julia-win64/Make.user + > echo 'ifeq ($(BUILDROOT),$(JULIAHOME)) + > $(error "in-tree build disabled") + > endif' >> Make.user + > make -C julia-win32 # build for Windows x86 in julia-win32 folder + > make -C julia-win64 # build for Windows x86-64 in julia-win64 folder + > ``` + 7. Run Julia using the Julia executables directly ```sh usr/bin/julia.exe diff --git a/base/Enums.jl b/base/Enums.jl index 9e8a144da1e588..13976a72d8e5fe 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -45,8 +45,9 @@ julia> f(apple) "I'm a Fruit with value: 1" ``` -`BaseType`, which defaults to `Int32`, must be a primitive subtype of Integer. Member values can be converted between -the enum type and `BaseType`. `read` and `write` perform these conversions automatically. +`BaseType`, which defaults to [`Int32`](@ref), must be a primitive subtype of `Integer`. +Member values can be converted between the enum type and `BaseType`. `read` and `write` +perform these conversions automatically. """ macro enum(T,syms...) if isempty(syms) diff --git a/base/Makefile b/base/Makefile index 04c97fda88e8df..02d68c08ea3cd9 100644 --- a/base/Makefile +++ b/base/Makefile @@ -55,7 +55,7 @@ else endif @echo "const libfftw_name = \"$(LIBFFTWNAME)\"" >> $@ @echo "const libfftwf_name = \"$(LIBFFTWFNAME)\"" >> $@ - @echo "const libllvm_version = \"$$($(LLVM_CONFIG_HOST) --version)\"" >> $@ + @echo "const libllvm_version_string = \"$$($(LLVM_CONFIG_HOST) --version)\"" >> $@ @echo "const VERSION_STRING = \"$(JULIA_VERSION)\"" >> $@ @echo "const TAGGED_RELEASE_BANNER = \"$(TAGGED_RELEASE_BANNER)\"" >> $@ @echo "const SYSCONFDIR = \"$(sysconfdir_rel)\"" >> $@ diff --git a/base/REPL.jl b/base/REPL.jl index 973322131e41a4..79a3ed861acb8e 100644 --- a/base/REPL.jl +++ b/base/REPL.jl @@ -633,6 +633,7 @@ function respond(f, repl, main; pass_empty = false) line = String(take!(buf)) if !isempty(line) || pass_empty reset(repl) + local val, bt try # note: value wrapped carefully here to ensure it doesn't get passed through expand response = eval(Main, Expr(:body, Expr(:return, Expr(:call, QuoteNode(f), QuoteNode(line))))) diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index f5626e5f5c57ab..d58aebe5f98329 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -282,7 +282,7 @@ function get_type_call(expr::Expr) found ? push!(args, typ) : push!(args, Any) end # use _methods_by_ftype as the function is supplied as a type - world = typemax(UInt) + world = ccall(:jl_get_world_counter, UInt, ()) mt = Base._methods_by_ftype(Tuple{ft, args...}, -1, world) length(mt) == 1 || return (Any, false) m = first(mt) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 440372def4d585..af3bfe47825dd7 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -503,7 +503,7 @@ julia> similar(trues(10,10), 2) false ``` -Since `BitArray`s can only store elements of type `Bool`, however, if you request a +Since `BitArray`s can only store elements of type [`Bool`](@ref), however, if you request a different element type it will create a regular `Array` instead: ```julia-repl diff --git a/base/array.jl b/base/array.jl index a4ae57bd971ae5..e7adc6e67eb2b2 100644 --- a/base/array.jl +++ b/base/array.jl @@ -266,7 +266,7 @@ end eye([T::Type=Float64,] m::Integer, n::Integer) `m`-by-`n` identity matrix. -The default element type is `Float64`. +The default element type is [`Float64`](@ref). """ function eye(::Type{T}, m::Integer, n::Integer) where T a = zeros(T,m,n) @@ -287,7 +287,7 @@ eye(::Type{T}, n::Integer) where {T} = eye(T, n, n) eye([T::Type=Float64,] n::Integer) `n`-by-`n` identity matrix. -The default element type is `Float64`. +The default element type is [`Float64`](@ref). """ eye(n::Integer) = eye(Float64, n) @@ -860,8 +860,8 @@ julia> deleteat!([6, 5, 4, 3, 2, 1], [true, false, true, false, true, false]) julia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2)) ERROR: ArgumentError: indices must be unique and sorted Stacktrace: - [1] _deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:873 - [2] deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:860 + [1] _deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:880 + [2] deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:867 ``` """ deleteat!(a::Vector, inds) = _deleteat!(a, inds) diff --git a/base/atomics.jl b/base/atomics.jl index 7374bad3f4f2e1..a2dfbef623b313 100644 --- a/base/atomics.jl +++ b/base/atomics.jl @@ -17,7 +17,7 @@ export # Disable 128-bit types on 32-bit Intel sytems due to LLVM problems; # see (fixed on LLVM 3.9) # 128-bit atomics do not exist on AArch32. -if (VersionNumber(Base.libllvm_version) < v"3.9-" && ARCH === :i686) || +if (Base.libllvm_version < v"3.9-" && ARCH === :i686) || startswith(string(ARCH), "arm") const inttypes = (Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64) @@ -330,8 +330,8 @@ alignment(::Type{T}) where {T} = ccall(:jl_alignment, Cint, (Csize_t,), sizeof(T for typ in atomictypes lt = llvmtypes[typ] ilt = llvmtypes[inttype(typ)] - rt = VersionNumber(Base.libllvm_version) >= v"3.6" ? "$lt, $lt*" : "$lt*" - irt = VersionNumber(Base.libllvm_version) >= v"3.6" ? "$ilt, $ilt*" : "$ilt*" + rt = Base.libllvm_version >= v"3.6" ? "$lt, $lt*" : "$lt*" + irt = Base.libllvm_version >= v"3.6" ? "$ilt, $ilt*" : "$ilt*" if VersionNumber(Base.libllvm_version) >= v"3.8" @eval getindex(x::Atomic{$typ}) = llvmcall($""" diff --git a/base/boot.jl b/base/boot.jl index d0a686e761bf50..23e803b81fe063 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -87,6 +87,7 @@ #struct LineNumberNode # line::Int +# file::Any # nominally Union{Symbol,Void} #end #struct LabelNode @@ -281,7 +282,8 @@ _new(:GotoNode, :Int) _new(:NewvarNode, :SlotNumber) _new(:QuoteNode, :ANY) _new(:SSAValue, :Int) -eval(:((::Type{LineNumberNode})(l::Int) = $(Expr(:new, :LineNumberNode, :l)))) +eval(:((::Type{LineNumberNode})(l::Int) = $(Expr(:new, :LineNumberNode, :l, nothing)))) +eval(:((::Type{LineNumberNode})(l::Int, f::ANY) = $(Expr(:new, :LineNumberNode, :l, :f)))) eval(:((::Type{GlobalRef})(m::Module, s::Symbol) = $(Expr(:new, :GlobalRef, :m, :s)))) eval(:((::Type{SlotNumber})(n::Int) = $(Expr(:new, :SlotNumber, :n)))) eval(:((::Type{TypedSlot})(n::Int, t::ANY) = $(Expr(:new, :TypedSlot, :n, :t)))) @@ -335,7 +337,7 @@ end # docsystem basics macro doc(x...) - atdoc(x...) + atdoc(__source__, x...) end macro __doc__(x) Expr(:escape, Expr(:block, Expr(:meta, :doc), x)) @@ -343,7 +345,7 @@ end macro doc_str(s) Expr(:escape, s) end -atdoc = (str, expr) -> Expr(:escape, expr) +atdoc = (source, str, expr) -> Expr(:escape, expr) atdoc!(λ) = global atdoc = λ diff --git a/base/c.jl b/base/c.jl index 410bb1e2f153e0..80c58a46406144 100644 --- a/base/c.jl +++ b/base/c.jl @@ -45,7 +45,7 @@ Culong """ Cwchar_t -Equivalent to the native `wchar_t` c-type (`Int32`). +Equivalent to the native `wchar_t` c-type ([`Int32`](@ref)). """ Cwchar_t diff --git a/base/combinatorics.jl b/base/combinatorics.jl index 920f6c23d944e6..645a9499f1c63f 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -2,29 +2,17 @@ # Factorials -const _fact_table64 = - Int64[1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800, - 87178291200,1307674368000,20922789888000,355687428096000,6402373705728000, - 121645100408832000,2432902008176640000] - -const _fact_table128 = - UInt128[0x00000000000000000000000000000001, 0x00000000000000000000000000000002, - 0x00000000000000000000000000000006, 0x00000000000000000000000000000018, - 0x00000000000000000000000000000078, 0x000000000000000000000000000002d0, - 0x000000000000000000000000000013b0, 0x00000000000000000000000000009d80, - 0x00000000000000000000000000058980, 0x00000000000000000000000000375f00, - 0x00000000000000000000000002611500, 0x0000000000000000000000001c8cfc00, - 0x0000000000000000000000017328cc00, 0x0000000000000000000000144c3b2800, - 0x00000000000000000000013077775800, 0x00000000000000000000130777758000, - 0x00000000000000000001437eeecd8000, 0x00000000000000000016beecca730000, - 0x000000000000000001b02b9306890000, 0x000000000000000021c3677c82b40000, - 0x0000000000000002c5077d36b8c40000, 0x000000000000003ceea4c2b3e0d80000, - 0x000000000000057970cd7e2933680000, 0x00000000000083629343d3dcd1c00000, - 0x00000000000cd4a0619fb0907bc00000, 0x00000000014d9849ea37eeac91800000, - 0x00000000232f0fcbb3e62c3358800000, 0x00000003d925ba47ad2cd59dae000000, - 0x0000006f99461a1e9e1432dcb6000000, 0x00000d13f6370f96865df5dd54000000, - 0x0001956ad0aae33a4560c5cd2c000000, 0x0032ad5a155c6748ac18b9a580000000, - 0x0688589cc0e9505e2f2fee5580000000, 0xde1bc4d19efcac82445da75b00000000] +const _fact_table64 = Vector{Int64}(20) +_fact_table64[1] = 1 +for n in 2:20 + _fact_table64[n] = _fact_table64[n-1] * n +end + +const _fact_table128 = Vector{UInt128}(34) +_fact_table128[1] = 1 +for n in 2:34 + _fact_table128[n] = _fact_table128[n-1] * n +end function factorial_lookup(n::Integer, table, lim) n < 0 && throw(DomainError()) diff --git a/base/complex.jl b/base/complex.jl index 836253b1d65fa6..237918f122f11d 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -1,5 +1,13 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +""" + Complex{T<:Real} <: Number + +Complex number type with real and imaginary part of type `T`. + +`Complex32`, `Complex64` and `Complex128` are aliases for +`Complex{Float16}`, `Complex{Float32}` and `Complex{Float64}` respectively. +""" struct Complex{T<:Real} <: Number re::T im::T @@ -603,19 +611,21 @@ function ^(z::Complex{T}, p::Complex{T})::Complex{T} where T<:AbstractFloat end end -function exp2(z::Complex{T}) where T +function exp2(z::Complex{T}) where T<:AbstractFloat er = exp2(real(z)) theta = imag(z) * log(convert(T, 2)) s, c = sincos(theta) Complex(er * c, er * s) end +exp2(z::Complex) = exp2(float(z)) -function exp10(z::Complex{T}) where T +function exp10(z::Complex{T}) where T<:AbstractFloat er = exp10(real(z)) theta = imag(z) * log(convert(T, 10)) s, c = sincos(theta) Complex(er * c, er * s) end +exp10(z::Complex) = exp10(float(z)) function ^(z::T, p::T) where T<:Complex if isinteger(p) diff --git a/base/ctypes.jl b/base/ctypes.jl index 387fdd9d8c7ddc..26640ed82bef50 100644 --- a/base/ctypes.jl +++ b/base/ctypes.jl @@ -6,7 +6,7 @@ """ Cuchar -Equivalent to the native `unsigned char` c-type (`UInt8`). +Equivalent to the native `unsigned char` c-type ([`UInt8`](@ref)). """ const Cuchar = UInt8 @@ -14,7 +14,7 @@ const Cuchar = UInt8 """ Cshort -Equivalent to the native `signed short` c-type (`Int16`). +Equivalent to the native `signed short` c-type ([`Int16`](@ref)). """ const Cshort = Int16 @@ -22,7 +22,7 @@ const Cshort = Int16 """ Cushort -Equivalent to the native `unsigned short` c-type (`UInt16`). +Equivalent to the native `unsigned short` c-type ([`UInt16`](@ref)). """ const Cushort = UInt16 @@ -30,7 +30,7 @@ const Cushort = UInt16 """ Cint -Equivalent to the native `signed int` c-type (`Int32`). +Equivalent to the native `signed int` c-type ([`Int32`](@ref)). """ const Cint = Int32 @@ -38,7 +38,7 @@ const Cint = Int32 """ Cuint -Equivalent to the native `unsigned int` c-type (`UInt32`). +Equivalent to the native `unsigned int` c-type ([`UInt32`](@ref)). """ const Cuint = UInt32 @@ -70,7 +70,7 @@ const Cssize_t = Int """ Cintmax_t -Equivalent to the native `intmax_t` c-type (`Int64`). +Equivalent to the native `intmax_t` c-type ([`Int64`](@ref)). """ const Cintmax_t = Int64 @@ -78,7 +78,7 @@ const Cintmax_t = Int64 """ Cuintmax_t -Equivalent to the native `uintmax_t` c-type (`UInt64`). +Equivalent to the native `uintmax_t` c-type ([`UInt64`](@ref)). """ const Cuintmax_t = UInt64 @@ -86,7 +86,7 @@ const Cuintmax_t = UInt64 """ Clonglong -Equivalent to the native `signed long long` c-type (`Int64`). +Equivalent to the native `signed long long` c-type ([`Int64`](@ref)). """ const Clonglong = Int64 @@ -94,7 +94,7 @@ const Clonglong = Int64 """ Culonglong -Equivalent to the native `unsigned long long` c-type (`UInt64`). +Equivalent to the native `unsigned long long` c-type ([`UInt64`](@ref)). """ const Culonglong = UInt64 @@ -102,7 +102,7 @@ const Culonglong = UInt64 """ Cfloat -Equivalent to the native `float` c-type (`Float32`). +Equivalent to the native `float` c-type ([`Float32`](@ref)). """ const Cfloat = Float32 @@ -110,6 +110,6 @@ const Cfloat = Float32 """ Cdouble -Equivalent to the native `double` c-type (`Float64`). +Equivalent to the native `double` c-type ([`Float64`](@ref)). """ const Cdouble = Float64 diff --git a/base/dates/accessors.jl b/base/dates/accessors.jl index d6ca8866430012..27c41d118dfc81 100644 --- a/base/dates/accessors.jl +++ b/base/dates/accessors.jl @@ -74,7 +74,7 @@ for func in (:year, :month) @doc """ $($name)(dt::TimeType) -> Int64 - The $($name) of a `Date` or `DateTime` as an `Int64`. + The $($name) of a `Date` or `DateTime` as an [`Int64`](@ref). """ $func(dt::TimeType) end end @@ -83,9 +83,10 @@ end week(dt::TimeType) -> Int64 Return the [ISO week date](https://en.wikipedia.org/wiki/ISO_week_date) of a `Date` or -`DateTime` as an `Int64`. Note that the first week of a year is the week that contains the -first Thursday of the year which can result in dates prior to January 4th being in the last -week of the previous year. For example `week(Date(2005,1,1))` is the 53rd week of 2004. +`DateTime` as an [`Int64`](@ref). Note that the first week of a year is the week that +contains the first Thursday of the year which can result in dates prior to January 4th +being in the last week of the previous year. For example `week(Date(2005,1,1))` is the 53rd +week of 2004. """ week(dt::TimeType) @@ -95,7 +96,7 @@ for func in (:day, :dayofmonth) @doc """ $($name)(dt::TimeType) -> Int64 - The day of month of a `Date` or `DateTime` as an `Int64`. + The day of month of a `Date` or `DateTime` as an [`Int64`](@ref). """ $func(dt::TimeType) end end @@ -103,7 +104,7 @@ end """ hour(dt::DateTime) -> Int64 -The hour of day of a `DateTime` as an `Int64`. +The hour of day of a `DateTime` as an [`Int64`](@ref). """ hour(dt::DateTime) @@ -113,7 +114,7 @@ for func in (:minute, :second, :millisecond) @doc """ $($name)(dt::DateTime) -> Int64 - The $($name) of a `DateTime` as an `Int64`. + The $($name) of a `DateTime` as an [`Int64`](@ref). """ $func(dt::DateTime) end end @@ -137,7 +138,7 @@ for func in (:hour, :minute, :second, :millisecond, :microsecond, :nanosecond) @doc """ $($name)(t::Time) -> Int64 - The $($name) of a `Time` as an `Int64`. + The $($name) of a `Time` as an [`Int64`](@ref). """ $func(t::Time) end end diff --git a/base/dates/adjusters.jl b/base/dates/adjusters.jl index 357faec442a27f..b93236e95bd9e5 100644 --- a/base/dates/adjusters.jl +++ b/base/dates/adjusters.jl @@ -253,8 +253,8 @@ tonext(dt::TimeType, dow::Int; same::Bool=false) = adjust(ISDAYOFWEEK[dow], same tonext(func::Function, dt::TimeType; step=Day(1), limit=10000, same=false) -> TimeType Adjusts `dt` by iterating at most `limit` iterations by `step` increments until `func` -returns `true`. `func` must take a single `TimeType` argument and return a `Bool`. `same` -allows `dt` to be considered in satisfying `func`. +returns `true`. `func` must take a single `TimeType` argument and return a [`Bool`](@ref). +`same` allows `dt` to be considered in satisfying `func`. """ function tonext(func::Function, dt::TimeType; step::Period=Day(1), negate=nothing, limit::Int=10000, same::Bool=false) func = deprecate_negate(:tonext, func, "func,dt", negate) @@ -274,8 +274,8 @@ toprev(dt::TimeType, dow::Int; same::Bool=false) = adjust(ISDAYOFWEEK[dow], same toprev(func::Function, dt::TimeType; step=Day(-1), limit=10000, same=false) -> TimeType Adjusts `dt` by iterating at most `limit` iterations by `step` increments until `func` -returns `true`. `func` must take a single `TimeType` argument and return a `Bool`. `same` -allows `dt` to be considered in satisfying `func`. +returns `true`. `func` must take a single `TimeType` argument and return a [`Bool`](@ref). +`same` allows `dt` to be considered in satisfying `func`. """ function toprev(func::Function, dt::TimeType; step::Period=Day(-1), negate=nothing, limit::Int=10000, same::Bool=false) func = deprecate_negate(:toprev, func, "func,dt", negate) diff --git a/base/dates/conversions.jl b/base/dates/conversions.jl index 9016c5600d149b..853f20b01cc771 100644 --- a/base/dates/conversions.jl +++ b/base/dates/conversions.jl @@ -53,7 +53,7 @@ end datetime2unix(dt::DateTime) -> Float64 Takes the given `DateTime` and returns the number of seconds -since the unix epoch `1970-01-01T00:00:00` as a `Float64`. +since the unix epoch `1970-01-01T00:00:00` as a [`Float64`](@ref). """ datetime2unix(dt::DateTime) = (value(dt) - UNIXEPOCH) / 1000.0 @@ -116,6 +116,6 @@ end datetime2julian(dt::DateTime) -> Float64 Takes the given `DateTime` and returns the number of Julian calendar days since the julian -epoch `-4713-11-24T12:00:00` as a `Float64`. +epoch `-4713-11-24T12:00:00` as a [`Float64`](@ref). """ datetime2julian(dt::DateTime) = (value(dt) - JULIANEPOCH) / 86400000.0 diff --git a/base/dates/periods.jl b/base/dates/periods.jl index 7fbba3d59f86fb..27eafa5774ea16 100644 --- a/base/dates/periods.jl +++ b/base/dates/periods.jl @@ -33,7 +33,7 @@ for period in (:Year, :Month, :Week, :Day, :Hour, :Minute, :Second, :Millisecond $($period_str)(v) Construct a `$($period_str)` object with the given `v` value. Input must be - losslessly convertible to an `Int64`. + losslessly convertible to an [`Int64`](@ref). """ $period(v) end end diff --git a/base/dates/query.jl b/base/dates/query.jl index effdd68a1bbdf7..2e632e239566b8 100644 --- a/base/dates/query.jl +++ b/base/dates/query.jl @@ -101,7 +101,7 @@ dayofyear(y, m, d) = MONTHDAYS[m] + d + (m > 2 && isleapyear(y)) """ dayofweek(dt::TimeType) -> Int64 -Returns the day of the week as an `Int64` with `1 = Monday, 2 = Tuesday, etc.`. +Returns the day of the week as an [`Int64`](@ref) with `1 = Monday, 2 = Tuesday, etc.`. """ dayofweek(dt::TimeType) = dayofweek(days(dt)) diff --git a/base/dates/rounding.jl b/base/dates/rounding.jl index b1714fff075ef3..8adbf80902b57b 100644 --- a/base/dates/rounding.jl +++ b/base/dates/rounding.jl @@ -27,7 +27,7 @@ epochms2datetime(i) = DateTime(UTM(DATETIMEEPOCH + Int64(i))) date2epochdays(dt::Date) -> Int64 Takes the given `Date` and returns the number of days since the rounding epoch -(`0000-01-01T00:00:00`) as an `Int64`. +(`0000-01-01T00:00:00`) as an [`Int64`](@ref). """ date2epochdays(dt::Date) = value(dt) - DATEEPOCH @@ -35,7 +35,7 @@ date2epochdays(dt::Date) = value(dt) - DATEEPOCH datetime2epochms(dt::DateTime) -> Int64 Takes the given `DateTime` and returns the number of milliseconds since the rounding epoch -(`0000-01-01T00:00:00`) as an `Int64`. +(`0000-01-01T00:00:00`) as an [`Int64`](@ref). """ datetime2epochms(dt::DateTime) = value(dt) - DATETIMEEPOCH diff --git a/base/dates/types.jl b/base/dates/types.jl index 87871c9ee9f5ac..12e3e62bf25f22 100644 --- a/base/dates/types.jl +++ b/base/dates/types.jl @@ -47,7 +47,7 @@ end Nanosecond(v) Construct a `Period` type with the given `v` value. Input must be losslessly convertible -to an `Int64`. +to an [`Int64`](@ref). """ Period(v) @@ -173,7 +173,7 @@ argerror() = Nullable{ArgumentError}() """ DateTime(y, [m, d, h, mi, s, ms]) -> DateTime -Construct a `DateTime` type by parts. Arguments must be convertible to `Int64`. +Construct a `DateTime` type by parts. Arguments must be convertible to [`Int64`](@ref). """ function DateTime(y::Int64, m::Int64=1, d::Int64=1, h::Int64=0, mi::Int64=0, s::Int64=0, ms::Int64=0) @@ -197,7 +197,7 @@ end """ Date(y, [m, d]) -> Date -Construct a `Date` type by parts. Arguments must be convertible to `Int64`. +Construct a `Date` type by parts. Arguments must be convertible to [`Int64`](@ref). """ function Date(y::Int64, m::Int64=1, d::Int64=1) err = validargs(Date, y, m, d) @@ -214,7 +214,7 @@ end """ Time(h, [mi, s, ms, us, ns]) -> Time -Construct a `Time` type by parts. Arguments must be convertible to `Int64`. +Construct a `Time` type by parts. Arguments must be convertible to [`Int64`](@ref). """ function Time(h::Int64, mi::Int64=0, s::Int64=0, ms::Int64=0, us::Int64=0, ns::Int64=0) err = validargs(Time, h, mi, s, ms, us, ns) diff --git a/base/deprecated.jl b/base/deprecated.jl index e882c3be8481a3..5c844f33d238ea 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -200,7 +200,7 @@ end # Deprecate vectorized unary functions over sparse matrices in favor of compact broadcast syntax (#17265). for f in (:sin, :sinh, :sind, :asin, :asinh, :asind, :tan, :tanh, :tand, :atan, :atanh, :atand, - :sinpi, :cosc, :ceil, :floor, :trunc, :round, :real, :imag, + :sinpi, :cosc, :ceil, :floor, :trunc, :round, :log1p, :expm1, :abs, :abs2, :log, :log2, :log10, :exp, :exp2, :exp10, :sinc, :cospi, :cos, :cosh, :cosd, :acos, :acosd, diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 005d4a6a9f881d..bd9af3efe71d77 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -83,9 +83,11 @@ function initmeta(m::Module = current_module()) end function signature!(tv, expr::Expr) - if isexpr(expr, (:call, :macrocall)) + is_macrocall = isexpr(expr, :macrocall) + if is_macrocall || isexpr(expr, :call) sig = :(Union{Tuple{}}) - for arg in expr.args[2:end] + first_arg = is_macrocall ? 3 : 2 # skip function arguments + for arg in expr.args[first_arg:end] isexpr(arg, :parameters) && continue if isexpr(arg, :kw) # optional arg push!(sig.args, :(Tuple{$(sig.args[end].args[2:end]...)})) @@ -167,10 +169,10 @@ _docstr(doc::DocStr, data) = (doc.data = merge(data, doc.data); doc) macro ref(x) binding = bindingexpr(namify(x)) typesig = signature(x) - esc(docexpr(binding, typesig)) + esc(docexpr(__source__, binding, typesig)) end -docexpr(args...) = Expr(:call, docstr, args...) +docexpr(__source__, args...) = Expr(:call, docstr, args...) function formatdoc(d::DocStr) buffer = IOBuffer() @@ -480,26 +482,27 @@ isfield(x) = isexpr(x, :.) && # ========================= """ - Docs.metadata(expr) + Docs.metadata(source, expr) Build a `Dict` expression containing metadata captured from the expression `expr`. Fields that may be included in the returned `Dict`: -- `:path`: String representing the file where `expr` is defined. +- `:path`: Symbol representing the file where `expr` is defined. - `:linenumber`: Linenumber where `expr` is defined. - `:module`: Module where the docstring is defined. - `:fields`: `Dict` of all field docs found in `expr`. Only for concrete types. """ -function metadata(expr) +function metadata(__source__, expr) args = [] # Filename and linenumber of the docstring. - push!(args, :($(Pair)(:path, $(Base).@__FILE__))) - push!(args, :($(Pair)(:linenumber, $(unsafe_load(cglobal(:jl_lineno, Cint)))))) + __file__ = isa(__source__.file, Symbol) ? String(__source__.file) : "" + push!(args, Pair(:path, __file__)) + push!(args, Pair(:linenumber, __source__.line)) # Module in which the docstring is defined. push!(args, :($(Pair)(:module, $(current_module)()))) - # Field docs for concrete types. if isexpr(expr, :type) + # Field docs for concrete types. fields = [] tmp = nothing for each in expr.args[3].args @@ -516,37 +519,36 @@ function metadata(expr) :($(Dict)($(args...))) end -function keyworddoc(str, def) - docstr = esc(docexpr(lazy_iterpolate(str), metadata(def))) - :($(keywords)[$(esc(quot(def.name)))] = $docstr) +function keyworddoc(__source__, str, def) + docstr = esc(docexpr(__source__, lazy_iterpolate(str), metadata(__source__, def))) + return :($(keywords)[$(esc(quot(def.name)))] = $docstr) end -function objectdoc(str, def, expr, sig = :(Union{})) +function objectdoc(__source__, str, def, expr, sig = :(Union{})) binding = esc(bindingexpr(namify(expr))) - docstr = esc(docexpr(lazy_iterpolate(str), metadata(expr))) + docstr = esc(docexpr(__source__, lazy_iterpolate(str), metadata(__source__, expr))) quote $(esc(def)) $(doc!)($binding, $docstr, $(esc(sig))) end end -function calldoc(str, def) +function calldoc(__source__, str, def) args = def.args[2:end] if isempty(args) || all(validcall, args) - objectdoc(str, nothing, def, signature(def)) + objectdoc(__source__, str, nothing, def, signature(def)) else docerror(def) end end validcall(x) = isa(x, Symbol) || isexpr(x, (:(::), :..., :kw, :parameters)) -function moduledoc(meta, def, def′) +function moduledoc(__source__, meta, def, def′) name = namify(def′) docex = Expr(:call, doc!, bindingexpr(name), - docexpr(lazy_iterpolate(meta), metadata(name)) - ) + docexpr(__source__, lazy_iterpolate(meta), metadata(__source__, name))) if def === nothing - esc(:(eval($name, $(quot(docex))))) + esc(:($eval($name, $(quot(docex))))) else def = unblock(def) block = def.args[3].args @@ -560,18 +562,18 @@ function moduledoc(meta, def, def′) end # Shares a single doc, `meta`, between several expressions from the tuple expression `ex`. -function multidoc(meta, ex, define) +function multidoc(__source__, meta, ex, define) out = Expr(:toplevel) - str = docexpr(lazy_iterpolate(meta), metadata(ex)) + str = docexpr(__source__, lazy_iterpolate(meta), metadata(__source__, ex)) ref = Ref{DocStr}() for (n, arg) in enumerate(ex.args) # The first `arg` to be documented needs to also create the docstring for the group. # Subsequent `arg`s just need `ref` to be able to find the docstring without having # to create an entirely new one each. docstr = n === 1 ? :($(ref)[] = $str) : :($(ref)[]) - push!(out.args, :(@doc($docstr, $arg, $define))) + push!(out.args, docm(__source__, docstr, arg, define)) end - esc(out) + return out end """ @@ -599,7 +601,7 @@ function __doc__!(meta, def, define) # the Base image). We just need to convert each `@__doc__` marker to an `@doc`. finddoc(def) do each each.head = :macrocall - each.args = [Symbol("@doc"), meta, each.args[end], define] + each.args = [Symbol("@doc"), nothing, meta, each.args[end], define] # TODO: forward line number info end else # `def` has already been defined during Base image gen so we just need to find and @@ -642,12 +644,12 @@ const BINDING_HEADS = [:typealias, :const, :global, :(=)] # deprecation: remove isquotedmacrocall(x) = isexpr(x, :copyast, 1) && isa(x.args[1], QuoteNode) && - isexpr(x.args[1].value, :macrocall, 1) + isexpr(x.args[1].value, :macrocall, 2) # Simple expressions / atoms the may be documented. isbasicdoc(x) = isexpr(x, :.) || isa(x, Union{QuoteNode, Symbol}) is_signature(x) = isexpr(x, :call) || (isexpr(x, :(::), 2) && isexpr(x.args[1], :call)) || isexpr(x, :where) -function docm(meta, ex, define = true) +function docm(source::LineNumberNode, meta, ex, define = true) # Some documented expressions may be decorated with macro calls which obscure the actual # expression. Expand the macro calls and remove extra blocks. x = unblock(macroexpand(ex)) @@ -663,7 +665,7 @@ function docm(meta, ex, define = true) # "..." # kw"if", kw"else" # - isa(x, Base.BaseDocs.Keyword) ? keyworddoc(meta, x) : + isa(x, Base.BaseDocs.Keyword) ? keyworddoc(source, meta, x) : # Method / macro definitions and "call" syntax. # @@ -673,9 +675,9 @@ function docm(meta, ex, define = true) # function f end # f(...) # - isexpr(x, FUNC_HEADS) && is_signature(x.args[1]) ? objectdoc(meta, def, x, signature(x)) : - isexpr(x, :function) && !isexpr(x.args[1], :call) ? objectdoc(meta, def, x) : - isexpr(x, :call) ? calldoc(meta, x) : + isexpr(x, FUNC_HEADS) && is_signature(x.args[1]) ? objectdoc(source, meta, def, x, signature(x)) : + isexpr(x, :function) && !isexpr(x.args[1], :call) ? objectdoc(source, meta, def, x) : + isexpr(x, :call) ? calldoc(source, meta, x) : # Type definitions. # @@ -683,7 +685,7 @@ function docm(meta, ex, define = true) # abstract T # bitstype N T # - isexpr(x, [:type, :abstract, :bitstype]) ? objectdoc(meta, def, x) : + isexpr(x, [:type, :abstract, :bitstype]) ? objectdoc(source, meta, def, x) : # "Bindings". Names that resolve to objects with different names, ie. # @@ -691,20 +693,20 @@ function docm(meta, ex, define = true) # T = S # global T = S # - isexpr(x, BINDING_HEADS) && !isexpr(x.args[1], :call) ? objectdoc(meta, def, x) : + isexpr(x, BINDING_HEADS) && !isexpr(x.args[1], :call) ? objectdoc(source, meta, def, x) : # Quoted macrocall syntax. `:@time` / `:(Base.@time)`. - isquotedmacrocall(x) ? objectdoc(meta, def, x) : + isquotedmacrocall(x) ? objectdoc(source, meta, def, x) : # Modules and baremodules. - isexpr(x, :module) ? moduledoc(meta, def, x) : + isexpr(x, :module) ? moduledoc(source, meta, def, x) : # Document several expressions with the same docstring. `a, b, c`. - isexpr(x, :tuple) ? multidoc(meta, x, define) : + isexpr(x, :tuple) ? multidoc(source, meta, x, define) : # Errors generated by calling `macroexpand` are passed back to the call site. isexpr(x, :error) ? esc(x) : # When documenting macro-generated code we look for embedded `@__doc__` calls. __doc__!(meta, x, define) ? esc(x) : # Any "basic" expression such as a bare function or module name or numeric literal. - isbasicdoc(x) ? objectdoc(meta, nothing, x) : + isbasicdoc(x) ? objectdoc(source, meta, nothing, x) : # All other expressions are undocumentable and should be handled on a case-by-case basis # with `@__doc__`. Unbound string literals are also undocumentable since they cannot be @@ -723,14 +725,14 @@ function docerror(ex) :($(error)($txt, "\n")) end -function docm(ex) +function docm(source::LineNumberNode, ex) if isexpr(ex, :->) - docm(ex.args...) + docm(source, ex.args...) elseif haskey(keywords, ex) parsedoc(keywords[ex]) elseif isa(ex, Union{Expr, Symbol}) binding = esc(bindingexpr(namify(ex))) - if isexpr(ex, [:call, :macrocall]) + if isexpr(ex, :call) || isexpr(ex, :macrocall) sig = esc(signature(ex)) :($(doc)($binding, $sig)) else @@ -749,11 +751,21 @@ include("utils.jl") # Swap out the bootstrap macro with the real one. Core.atdoc!(docm) +macro local_hygiene(expr) + # removes `esc` Exprs relative to the module argument to expand + # and resolves everything else relative to this (Doc) module + # this allows us to get good errors and backtraces + # from calling docm (by not using macros), + # while also getting macro-expansion correct (by using the macro-expander) + return expr +end function loaddocs(docs) + unescape = GlobalRef(Docs, Symbol("@local_hygiene")) for (mod, ex, str, file, line) in docs data = Dict(:path => string(file), :linenumber => line) doc = docstr(str, data) - eval(mod, :(@doc($doc, $ex, false))) + docstring = eval(mod, Expr(:body, Expr(:return, Expr(:call, QuoteNode(docm), QuoteNode(LineNumberNode(line, file)), QuoteNode(doc), QuoteNode(ex), false)))) # expand the real @doc macro now (using a hack because macroexpand takes current-module as an implicit argument) + eval(mod, Expr(:macrocall, unescape, nothing, docstring)) end empty!(docs) end diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 9134bbc3925f7b..ece074d231a1ac 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -81,7 +81,7 @@ Julia’s type system more than just a collection of object implementations. For abstract type Number end abstract type Real <: Number end -`Number` has no supertype, whereas `Real` is an abstract subtype of `Number`. +[`Number`](@ref) has no supertype, whereas [`Real`](@ref) is an abstract subtype of `Number`. """ kw"abstract type" @@ -124,7 +124,7 @@ primitive type declarations: The number after the name indicates how many bits of storage the type requires. Currently, only sizes that are multiples of 8 bits are supported. -The `Bool` declaration shows how a primitive type can be optionally +The [`Bool`](@ref) declaration shows how a primitive type can be optionally declared to be a subtype of some supertype. """ kw"primitive type" @@ -644,13 +644,6 @@ to be set after construction. See `struct` and the manual for more information. """ kw"mutable struct" -""" - @__LINE__ -> Int - -`@__LINE__` expands to the line number of the call-site. -""" -kw"@__LINE__" - """ ans diff --git a/base/docs/core.jl b/base/docs/core.jl index 9b8cf34c7f48a9..747afab704aa30 100644 --- a/base/docs/core.jl +++ b/base/docs/core.jl @@ -4,12 +4,8 @@ module CoreDocs import ..esc, ..push!, ..getindex, ..current_module, ..unsafe_load, ..Csize_t -function doc!(str, ex) - ptr = unsafe_load(Core.Intrinsics.cglobal(:jl_filename, Ptr{UInt8})) - len = ccall(:strlen, Csize_t, (Ptr{UInt8},), ptr) - file = ccall(:jl_symbol_n, Any, (Ptr{UInt8}, Csize_t), ptr, len) - line = unsafe_load(Core.Intrinsics.cglobal(:jl_lineno, Int32)) # Cint - push!(DOCS, (current_module(), ex, str, file, line)) +function doc!(source::LineNumberNode, str, ex) + push!(DOCS, (current_module(), ex, str, source.file, source.line)) end const DOCS = Array{Any, 1}() @@ -18,11 +14,12 @@ isexpr(x, h) = isa(x, Expr) && x.head === h lazy_iterpolate(s::AbstractString) = Expr(:call, Core.svec, s) lazy_iterpolate(x) = isexpr(x, :string) ? Expr(:call, Core.svec, x.args...) : x -function docm(str, x) - out = esc(Expr(:call, doc!, lazy_iterpolate(str), Expr(:quote, x))) +function docm(source::LineNumberNode, str, x) + out = esc(Expr(:call, doc!, QuoteNode(source), lazy_iterpolate(str), Expr(:quote, x))) isexpr(x, :module) ? Expr(:toplevel, out, esc(x)) : isexpr(x, :call) ? out : Expr(:block, esc(x), out) end -docm(x) = isexpr(x, :->) ? docm(x.args[1], x.args[2].args[2]) : error("invalid '@doc'.") +docm(source::LineNumberNode, x) = + isexpr(x, :->) ? docm(source, x.args[1], x.args[2].args[2]) : error("invalid '@doc'.") end diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index ac2f43e33778e3..a3f2530e4fef36 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -229,7 +229,7 @@ julia> Float32(1/3, RoundUp) See [`RoundingMode`](@ref) for available rounding modes. """ -Float32 +Float32(x) """ Mmap.mmap(io::Union{IOStream,AbstractString,Mmap.AnonymousMmap}[, type::Type{Array{T,N}}, dims, offset]; grow::Bool=true, shared::Bool=true) @@ -243,7 +243,7 @@ determines how the bytes of the array are interpreted. Note that the file must b binary format, and no format conversions are possible (this is a limitation of operating systems, not Julia). -`dims` is a tuple or single `Integer` specifying the size or length of the array. +`dims` is a tuple or single [`Integer`](@ref) specifying the size or length of the array. The file is passed via the stream argument, either as an open `IOStream` or filename string. When you initialize the stream, use `"r"` for a "read-only" array, and `"w+"` to create a @@ -814,7 +814,7 @@ julia> Float64(pi, RoundUp) See [`RoundingMode`](@ref) for available rounding modes. """ -Float64 +Float64(x) """ union(s1,s2...) @@ -1061,7 +1061,7 @@ For arrays, this constructs an array with the same binary data as the given array, but with the specified element type. For example, `reinterpret(Float32, UInt32(7))` interprets the 4 bytes corresponding to `UInt32(7)` as a -`Float32`. +[`Float32`](@ref). !!! warning @@ -1147,8 +1147,8 @@ searchsortedfirst """ big(x) -Convert a number to a maximum precision representation (typically `BigInt` or `BigFloat`). -See [`BigFloat`](@ref) for information about some pitfalls with floating-point numbers. +Convert a number to a maximum precision representation (typically [`BigInt`](@ref) or +`BigFloat`). See [`BigFloat`](@ref) for information about some pitfalls with floating-point numbers. """ big @@ -1431,25 +1431,13 @@ recurses infinitely. """ StackOverflowError -""" - BigInt(x) - -Create an arbitrary precision integer. `x` may be an `Int` (or anything that can be -converted to an `Int`). The usual mathematical operators are defined for this type, and -results are promoted to a `BigInt`. - -Instances can be constructed from strings via [`parse`](@ref), or using the `big` -string literal. -""" -BigInt - """ ==(x, y) -Generic equality operator, giving a single `Bool` result. Falls back to `===`. Should be -implemented for all types with a notion of equality, based on the abstract value that an -instance represents. For example, all numeric types are compared by numeric value, ignoring -type. Strings are compared as sequences of characters, ignoring encoding. +Generic equality operator, giving a single [`Bool`](@ref) result. Falls back to `===`. +Should be implemented for all types with a notion of equality, based on the abstract value +that an instance represents. For example, all numeric types are compared by numeric value, +ignoring type. Strings are compared as sequences of characters, ignoring encoding. Follows IEEE semantics for floating-point numbers. @@ -1946,7 +1934,7 @@ done Convert `x` to a value of type `T`. -If `T` is an `Integer` type, an [`InexactError`](@ref) will be raised if `x` +If `T` is an [`Integer`](@ref) type, an [`InexactError`](@ref) will be raised if `x` is not representable by `T`, for example if `x` is not integer-valued, or is outside the range supported by `T`. @@ -1960,7 +1948,7 @@ Stacktrace: [1] convert(::Type{Int64}, ::Float64) at ./float.jl:680 ``` -If `T` is a `AbstractFloat` or `Rational` type, +If `T` is a [`AbstractFloat`](@ref) or [`Rational`](@ref) type, then it will return the closest value to `x` representable by `T`. ```jldoctest @@ -2172,7 +2160,7 @@ isvalid(value) isvalid(T, value) -> Bool Returns `true` if the given value is valid for that type. Types currently can -be either `Char` or `String`. Values for `Char` can be of type `Char` or `UInt32`. +be either `Char` or `String`. Values for `Char` can be of type `Char` or [`UInt32`](@ref). Values for `String` can be of that type, or `Vector{UInt8}`. """ isvalid(T,value) @@ -2414,3 +2402,81 @@ seekend Integer division was attempted with a denominator value of 0. """ DivideError + +""" + Number + +Abstract supertype for all number types. +""" +Number + +""" + Real <: Number + +Abstract supertype for all real numbers. +""" +Real + +""" + AbstractFloat <: Real + +Abstract supertype for all floating point numbers. +""" +AbstractFloat + +""" + Integer <: Real + +Abstract supertype for all integers. +""" +Integer + +""" + Signed <: Integer + +Abstract supertype for all signed integers. +""" +Signed + +""" + Unsigned <: Integer + +Abstract supertype for all unsigned integers. +""" +Unsigned + +""" + Bool <: Integer + +Boolean type. +""" +Bool + +for bit in (16, 32, 64) + @eval begin + """ + Float$($bit) <: AbstractFloat + + $($bit)-bit floating point number type. + """ + $(Symbol("Float", bit)) + end +end + +for bit in (8, 16, 32, 64, 128) + @eval begin + """ + Int$($bit) <: Signed + + $($bit)-bit signed integer type. + """ + $(Symbol("Int", bit)) + + """ + UInt$($bit) <: Unsigned + + $($bit)-bit unsigned integer type. + """ + $(Symbol("UInt", bit)) + end +end diff --git a/base/docs/utils.jl b/base/docs/utils.jl index 0daf26f78c183d..895edf349e5be8 100644 --- a/base/docs/utils.jl +++ b/base/docs/utils.jl @@ -190,7 +190,7 @@ function repl(io::IO, s::Symbol) $(_repl(s)) end end -isregex(x) = isexpr(x, :macrocall, 2) && x.args[1] === Symbol("@r_str") && !isempty(x.args[2]) +isregex(x) = isexpr(x, :macrocall, 3) && x.args[1] === Symbol("@r_str") && !isempty(x.args[3]) repl(io::IO, ex::Expr) = isregex(ex) ? :(apropos($io, $ex)) : _repl(ex) repl(io::IO, str::AbstractString) = :(apropos($io, $str)) repl(io::IO, other) = :(@doc $(esc(other))) @@ -414,6 +414,7 @@ Strip all Markdown markup from x, leaving the result in plain text. Used internally by apropos to make docstrings containing more than one markdown element searchable. """ +stripmd(x::ANY) = string(x) # for random objects interpolated into the docstring stripmd(x::AbstractString) = x # base case stripmd(x::Void) = " " stripmd(x::Vector) = string(map(stripmd, x)...) diff --git a/base/error.jl b/base/error.jl index 108f5c83716d4a..f26df61ee91d85 100644 --- a/base/error.jl +++ b/base/error.jl @@ -98,7 +98,7 @@ end """ ExponentialBackOff(; n=1, first_delay=0.05, max_delay=10.0, factor=5.0, jitter=0.1) -A `Float64` iterator of length `n` whose elements exponentially increase at a +A [`Float64`](@ref) iterator of length `n` whose elements exponentially increase at a rate in the interval `factor` * (1 ± `jitter`). The first element is `first_delay` and all elements are clamped to `max_delay`. """ diff --git a/base/exports.jl b/base/exports.jl index 5109fdfe22c76f..b9bd9ecebe427f 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1249,6 +1249,7 @@ export # parser internal @__FILE__, @__DIR__, + @__LINE__, @int128_str, @uint128_str, @big_str, diff --git a/base/expr.jl b/base/expr.jl index 21d66ec4a445c8..d23a1909701f64 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -276,9 +276,16 @@ end remove_linenums!(ex) = ex function remove_linenums!(ex::Expr) - filter!(x->!((isa(x,Expr) && x.head === :line) || isa(x,LineNumberNode)), ex.args) + if ex.head === :body || ex.head === :block || ex.head === :quote + # remove line number expressions from metadata (not argument literal or inert) position + filter!(ex.args) do x + isa(x, Expr) && x.head === :line && return false + isa(x, LineNumberNode) && return false + return true + end + end for subex in ex.args remove_linenums!(subex) end - ex + return ex end diff --git a/base/fastmath.jl b/base/fastmath.jl index 6eca987d0703b2..a66762c2eb6bb7 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -251,7 +251,7 @@ sqrt_fast(x::FloatTypes) = sqrt_llvm_fast(x) const libm = Base.libm_name for f in (:acos, :acosh, :asin, :asinh, :atan, :atanh, :cbrt, :cos, - :cosh, :exp2, :exp, :expm1, :lgamma, :log10, :log1p, :log2, + :cosh, :exp2, :expm1, :lgamma, :log10, :log1p, :log2, :log, :sin, :sinh, :tan, :tanh) f_fast = fast_op[f] @eval begin diff --git a/base/file.jl b/base/file.jl index b344e264b79ecd..b9e85066eaaaae 100644 --- a/base/file.jl +++ b/base/file.jl @@ -359,6 +359,7 @@ mktemp(parent) mktempdir(parent=tempdir()) Create a temporary directory in the `parent` directory and return its path. +If `parent` does not exist, throw an error. """ mktempdir(parent) @@ -366,7 +367,8 @@ mktempdir(parent) """ mktemp(f::Function, parent=tempdir()) -Apply the function `f` to the result of `mktemp(parent)` and remove the temporary file upon completion. +Apply the function `f` to the result of [`mktemp(parent)`](@ref) and remove the +temporary file upon completion. """ function mktemp(fn::Function, parent=tempdir()) (tmp_path, tmp_io) = mktemp(parent) @@ -381,8 +383,8 @@ end """ mktempdir(f::Function, parent=tempdir()) -Apply the function `f` to the result of `mktempdir(parent)` and remove the temporary -directory upon completion. +Apply the function `f` to the result of [`mktempdir(parent)`](@ref) and remove the +temporary directory upon completion. """ function mktempdir(fn::Function, parent=tempdir()) tmpdir = mktempdir(parent) diff --git a/base/float.jl b/base/float.jl index 68d0d5138f0fe1..65836552b2b313 100644 --- a/base/float.jl +++ b/base/float.jl @@ -5,25 +5,25 @@ """ Inf16 -Positive infinity of type `Float16`. +Positive infinity of type [`Float16`](@ref). """ const Inf16 = bitcast(Float16, 0x7c00) """ NaN16 -A not-a-number value of type `Float16`. +A not-a-number value of type [`Float16`](@ref). """ const NaN16 = bitcast(Float16, 0x7e00) """ Inf32 -Positive infinity of type `Float32`. +Positive infinity of type [`Float32`](@ref). """ const Inf32 = bitcast(Float32, 0x7f800000) """ NaN32 -A not-a-number value of type `Float32`. +A not-a-number value of type [`Float32`](@ref). """ const NaN32 = bitcast(Float32, 0x7fc00000) const Inf64 = bitcast(Float64, 0x7ff0000000000000) @@ -32,13 +32,13 @@ const NaN64 = bitcast(Float64, 0x7ff8000000000000) """ Inf -Positive infinity of type `Float64`. +Positive infinity of type [`Float64`](@ref). """ const Inf = Inf64 """ NaN -A not-a-number value of type `Float64`. +A not-a-number value of type [`Float64`](@ref). """ const NaN = NaN64 @@ -750,8 +750,8 @@ of `x` is different, then the larger of the two is taken, that is eps(x) == max(x-prevfloat(x), nextfloat(x)-x) The exceptions to this rule are the smallest and largest finite values -(e.g. `nextfloat(-Inf)` and `prevfloat(Inf)` for `Float64`), which round to the smaller of -the values. +(e.g. `nextfloat(-Inf)` and `prevfloat(Inf)` for [`Float64`](@ref)), which round to the +smaller of the values. The rationale for this behavior is that `eps` bounds the floating point rounding error. Under the default `RoundNearest` rounding mode, if ``y`` is a real number and ``x`` diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index e75486a46257c5..a5973c7d99986a 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -78,7 +78,7 @@ julia> round(pi, 3, 2) !!! note Rounding to specified digits in bases other than 2 can be inexact when - operating on binary floating point numbers. For example, the `Float64` + operating on binary floating point numbers. For example, the [`Float64`](@ref) value represented by `1.15` is actually *less* than 1.15, yet will be rounded to 1.2. diff --git a/base/gmp.jl b/base/gmp.jl index 2e7c667b07d3b6..07926f98650423 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -37,7 +37,11 @@ else error("GMP: cannot determine the type mp_limb_t (__gmp_bits_per_limb == $GMP_BITS_PER_LIMB)") end +""" + BigInt <: Integer +Arbitrary precision integer type. +""" mutable struct BigInt <: Integer alloc::Cint size::Cint @@ -50,6 +54,26 @@ mutable struct BigInt <: Integer end end +""" + BigInt(x) + +Create an arbitrary precision integer. `x` may be an `Int` (or anything that can be +converted to an `Int`). The usual mathematical operators are defined for this type, and +results are promoted to a [`BigInt`](@ref). + +Instances can be constructed from strings via [`parse`](@ref), or using the `big` +string literal. + +```jldoctest +julia> parse(BigInt, "42") +42 + +julia> big"313" +313 +``` +""" +BigInt(x) + function __init__() try if gmp_version().major != GMP_VERSION.major || gmp_bits_per_limb() != GMP_BITS_PER_LIMB diff --git a/base/inference.jl b/base/inference.jl index 9f73259dafcf0d..8ea12fd2b2eac1 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -36,8 +36,6 @@ struct InferenceParams end end -const UNION_SPLIT_MISMATCH_ERROR = false - # alloc_elim_pass! relies on `Slot_AssignedOnce | Slot_UsedUndef` being # SSA. This should be true now but can break if we start to track conditional # constants. e.g. @@ -220,6 +218,8 @@ mutable struct InferenceState if isa(atyp, DataType) && isdefined(atyp, :instance) # replace singleton types with their equivalent Const object atyp = Const(atyp.instance) + elseif isconstType(atyp) + atype = Const(atyp.parameters[1]) else atyp = rewrap_unionall(atyp, linfo.specTypes) end @@ -999,7 +999,7 @@ function apply_type_tfunc(headtypetype::ANY, args::ANY...) ai = args[i] if isType(ai) aip1 = ai.parameters[1] - canconst &= isleaftype(aip1) + canconst &= !has_free_typevars(aip1) push!(tparams, aip1) elseif isa(ai, Const) && (isa(ai.val, Type) || isa(ai.val, TypeVar) || valid_tparam(ai.val)) push!(tparams, ai.val) @@ -1410,10 +1410,6 @@ function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState) add_mt_backedge(ftname.mt, argtype, sv) update_valid_age!(min_valid[1], max_valid[1], sv) end - if isempty(applicable) - # TODO: this is needed because type intersection is wrong in some cases - return Any - end #print("=> ", rettype, "\n") return rettype end @@ -1577,13 +1573,6 @@ function return_type_tfunc(argtypes::ANY, vtypes::VarTable, sv::InferenceState) if isa(af_argtype, DataType) && af_argtype <: Tuple argtypes_vec = Any[aft, af_argtype.parameters...] astype = argtypes_to_type(argtypes_vec) - if !(aft ⊑ Builtin) && - _methods_by_ftype(astype, 0, sv.params.world, - UInt[typemin(UInt)], UInt[typemax(UInt)]) !== false - # return_type returns Bottom if no methods match, even though - # inference doesn't necessarily. - return Const(Bottom) - end if isa(aft, Const) rt = abstract_call(aft.val, (), argtypes_vec, vtypes, sv) elseif isconstType(aft) @@ -1782,6 +1771,10 @@ function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vect else return Any end + if !isa(body, Type) && !isa(body, TypeVar) + return Any + end + has_free_typevars(body) || return body if isa(argtypes[2], Const) tv = argtypes[2].val elseif isa(argtypes[2], PartialTypeVar) @@ -1792,9 +1785,6 @@ function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vect return Any end !isa(tv, TypeVar) && return Any - if !isa(body, Type) && !isa(body, TypeVar) - return Any - end theunion = UnionAll(tv, body) ret = canconst ? abstract_eval_constant(theunion) : Type{theunion} return ret @@ -1862,8 +1852,8 @@ function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vect t = pure_eval_call(f, argtypes, atype, sv) t !== false && return t - if istopfunction(tm, f, :promote_type) || istopfunction(tm, f, :typejoin) - return Type + if istopfunction(tm, f, :typejoin) || f === return_type + return Type # don't try to infer these function edges directly -- it won't actually come up with anything useful elseif length(argtypes) == 2 && istopfunction(tm, f, :typename) return typename_static(argtypes[2]) end @@ -3587,7 +3577,7 @@ function invoke_NF(argexprs, etype::ANY, atypes, sv, atype_unlimited::ANY, all = false end end - if UNION_SPLIT_MISMATCH_ERROR && all + if all error_label === nothing && (error_label = genlabel(sv)) push!(stmts, GotoNode(error_label.label)) else @@ -4140,39 +4130,38 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference end do_coverage = coverage_enabled() - if do_coverage - line = method.line - if !isempty(stmts) && isa(stmts[1], LineNumberNode) - line = (shift!(stmts)::LineNumberNode).line + line::Int = method.line + file = method.file + if !isempty(stmts) + if !do_coverage && all(inlining_ignore, stmts) + empty!(stmts) + elseif isa(stmts[1], LineNumberNode) + linenode = shift!(stmts)::LineNumberNode + line = linenode.line + isa(linenode.file, Symbol) && (file = linenode.file) end + end + if do_coverage # Check if we are switching module, which is necessary to catch user # code inlined into `Base` with `--code-coverage=user`. # Assume we are inlining directly into `enclosing` instead of another # function inlined in it mod = method.module if mod === sv.mod - unshift!(stmts, Expr(:meta, :push_loc, method.file, + unshift!(stmts, Expr(:meta, :push_loc, file, method.name, line)) else - unshift!(stmts, Expr(:meta, :push_loc, method.file, + unshift!(stmts, Expr(:meta, :push_loc, file, method.name, line, mod)) end push!(stmts, Expr(:meta, :pop_loc)) elseif !isempty(stmts) - if all(inlining_ignore, stmts) - empty!(stmts) + unshift!(stmts, Expr(:meta, :push_loc, file, + method.name, line)) + if isa(stmts[end], LineNumberNode) + stmts[end] = Expr(:meta, :pop_loc) else - line::Int = method.line - if isa(stmts[1], LineNumberNode) - line = (shift!(stmts)::LineNumberNode).line - end - unshift!(stmts, Expr(:meta, :push_loc, method.file, - method.name, line)) - if isa(stmts[end], LineNumberNode) - stmts[end] = Expr(:meta, :pop_loc) - else - push!(stmts, Expr(:meta, :pop_loc)) - end + push!(stmts, Expr(:meta, :pop_loc)) end end if !isempty(stmts) && !propagate_inbounds @@ -5426,7 +5415,8 @@ end # especially try to make sure any recursive and leaf functions have concrete signatures, # since we won't be able to specialize & infer them at runtime -let fs = Any[typeinf_ext, typeinf, typeinf_edge, occurs_outside_getfield, pure_eval_call] +let fs = Any[typeinf_ext, typeinf, typeinf_edge, occurs_outside_getfield, pure_eval_call], + world = ccall(:jl_get_world_counter, UInt, ()) for x in t_ffunc_val push!(fs, x[3]) end @@ -5445,7 +5435,7 @@ let fs = Any[typeinf_ext, typeinf, typeinf_edge, occurs_outside_getfield, pure_e typ[i] = typ[i].ub end end - typeinf_type(m[3], Tuple{typ...}, m[2], true, InferenceParams(typemax(UInt))) + typeinf_type(m[3], Tuple{typ...}, m[2], true, InferenceParams(world)) end end end diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 5b959f063ea2af..34f77247364938 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -349,7 +349,7 @@ function code_warntype(io::IO, f, t::ANY) end code_warntype(f, t::ANY) = code_warntype(STDOUT, f, t) -typesof(args...) = Tuple{map(a->(isa(a,Type) ? Type{a} : typeof(a)), args)...} +typesof(args...) = Tuple{Any[ Core.Typeof(a) for a in args ]...} gen_call_with_extracted_types(fcn, ex0::Symbol) = Expr(:call, fcn, Meta.quot(ex0)) function gen_call_with_extracted_types(fcn, ex0) @@ -371,9 +371,9 @@ function gen_call_with_extracted_types(fcn, ex0) exret = Expr(:none) is_macro = false ex = expand(ex0) - if isa(ex0, Expr) && ex0.head == :macrocall # Make @edit @time 1+2 edit the macro + if isa(ex0, Expr) && ex0.head == :macrocall # Make @edit @time 1+2 edit the macro by using the types of the *expressions* is_macro = true - exret = Expr(:call, fcn, esc(ex0.args[1]), typesof(ex0.args[2:end]...)) + exret = Expr(:call, fcn, esc(ex0.args[1]), Tuple{#=__source__=#LineNumberNode, Any[ Core.Typeof(a) for a in ex0.args[3:end] ]...}) elseif !isa(ex, Expr) exret = Expr(:call, :error, "expression is not a function call or symbol") elseif ex.head == :call diff --git a/base/irrationals.jl b/base/irrationals.jl index d2d76abbc0df07..91d56999474a2e 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -2,6 +2,11 @@ ## general machinery for irrational mathematical constants +""" + Irrational <: Real + +Irrational number type. +""" struct Irrational{sym} <: Real end show(io::IO, x::Irrational{sym}) where {sym} = print(io, "$sym = $(string(float(x))[1:15])...") @@ -156,7 +161,7 @@ julia> pi π = 3.1415926535897... ``` """ -const pi = π +π, const pi = π """ e @@ -169,7 +174,7 @@ julia> e e = 2.7182818284590... ``` """ -const eu = e +e, const eu = e """ γ @@ -182,7 +187,7 @@ julia> eulergamma γ = 0.5772156649015... ``` """ -const eulergamma = γ +γ, const eulergamma = γ """ φ @@ -195,7 +200,7 @@ julia> golden φ = 1.6180339887498... ``` """ -const golden = φ +φ, const golden = φ """ catalan diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index f7418b6e38428d..164a895bfd7066 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -149,10 +149,10 @@ function isdiff(repo::GitRepo, treeish::AbstractString, paths::AbstractString="" diff = diff_tree(repo, tree, paths, cached=cached) result = count(diff) > 0 close(diff) + return result finally close(tree) end - return result end """ diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index 0d09fa998028d2..2b5c89cad03efc 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -18,6 +18,11 @@ # through the Hermitian and Symmetric views or exact symmetric or Hermitian elements which # is checked for and an error is thrown if the check fails. +# The internal structure is as follows +# - _chol! returns the factor and info without checking positive definiteness +# - chol/chol! returns the factor and checks for positive definiteness +# - cholfact/cholfact! returns Cholesky with checking positive definiteness + # FixMe? The dispatch below seems overly complicated. One simplification could be to # merge the two Cholesky types into one. It would remove the need for Val completely but # the cost would be extra unnecessary/unused fields for the unpivoted Cholesky and runtime @@ -27,9 +32,12 @@ struct Cholesky{T,S<:AbstractMatrix} <: Factorization{T} factors::S uplo::Char + info::BlasInt end -Cholesky{T}(A::AbstractMatrix{T}, uplo::Symbol) = Cholesky{T,typeof(A)}(A, char_uplo(uplo)) -Cholesky{T}(A::AbstractMatrix{T}, uplo::Char) = Cholesky{T,typeof(A)}(A, uplo) +Cholesky{T}(A::AbstractMatrix{T}, uplo::Symbol, info::BlasInt) = + Cholesky{T,typeof(A)}(A, char_uplo(uplo), info) +Cholesky{T}(A::AbstractMatrix{T}, uplo::Char, info::BlasInt) = + Cholesky{T,typeof(A)}(A, uplo, info) struct CholeskyPivoted{T,S<:AbstractMatrix} <: Factorization{T} factors::S @@ -49,11 +57,11 @@ end ## BLAS/LAPACK element types function _chol!(A::StridedMatrix{<:BlasFloat}, ::Type{UpperTriangular}) C, info = LAPACK.potrf!('U', A) - return @assertposdef UpperTriangular(C) info + return UpperTriangular(C), info end function _chol!(A::StridedMatrix{<:BlasFloat}, ::Type{LowerTriangular}) C, info = LAPACK.potrf!('L', A) - return @assertposdef LowerTriangular(C) info + return LowerTriangular(C), info end ## Non BLAS/LAPACK element types (generic) @@ -64,7 +72,10 @@ function _chol!(A::AbstractMatrix, ::Type{UpperTriangular}) for i = 1:k - 1 A[k,k] -= A[i,k]'A[i,k] end - Akk = _chol!(A[k,k], UpperTriangular) + Akk, info = _chol!(A[k,k], UpperTriangular) + if info != 0 + return UpperTriangular(A), info + end A[k,k] = Akk AkkInv = inv(Akk') for j = k + 1:n @@ -75,7 +86,7 @@ function _chol!(A::AbstractMatrix, ::Type{UpperTriangular}) end end end - return UpperTriangular(A) + return UpperTriangular(A), convert(BlasInt, 0) end function _chol!(A::AbstractMatrix, ::Type{LowerTriangular}) n = checksquare(A) @@ -84,7 +95,10 @@ function _chol!(A::AbstractMatrix, ::Type{LowerTriangular}) for i = 1:k - 1 A[k,k] -= A[k,i]*A[k,i]' end - Akk = _chol!(A[k,k], LowerTriangular) + Akk, info = _chol!(A[k,k], LowerTriangular) + if info != 0 + return LowerTriangular(A), info + end A[k,k] = Akk AkkInv = inv(Akk) for j = 1:k @@ -99,30 +113,33 @@ function _chol!(A::AbstractMatrix, ::Type{LowerTriangular}) end end end - return LowerTriangular(A) + return LowerTriangular(A), convert(BlasInt, 0) end ## Numbers function _chol!(x::Number, uplo) rx = real(x) - if rx != abs(x) - throw(ArgumentError("x must be positive semidefinite")) - end - rxr = sqrt(rx) - convert(promote_type(typeof(x), typeof(rxr)), rxr) + rxr = sqrt(abs(rx)) + rval = convert(promote_type(typeof(x), typeof(rxr)), rxr) + rx == abs(x) ? (rval, convert(BlasInt, 0)) : (rval, convert(BlasInt, 1)) end +chol!(x::Number, uplo) = ((C, info) = _chol!(x, uplo); @assertposdef C info) + non_hermitian_error(f) = throw(ArgumentError("matrix is not symmetric/" * "Hermitian. This error can be avoided by calling $f(Hermitian(A)) " * "which will ignore either the upper or lower triangle of the matrix.")) # chol!. Destructive methods for computing Cholesky factor of real symmetric or Hermitian # matrix -chol!(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = - _chol!(A.uplo == 'U' ? A.data : LinAlg.copytri!(A.data, 'L', true), UpperTriangular) +function chol!(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) + C, info = _chol!(A.uplo == 'U' ? A.data : LinAlg.copytri!(A.data, 'L', true), UpperTriangular) + @assertposdef C info +end function chol!(A::StridedMatrix) ishermitian(A) || non_hermitian_error("chol!") - return _chol!(A, UpperTriangular) + C, info = _chol!(A, UpperTriangular) + @assertposdef C info end @@ -184,7 +201,7 @@ julia> chol(16) 4.0 ``` """ -chol(x::Number, args...) = _chol!(x, nothing) +chol(x::Number, args...) = ((C, info) = _chol!(x, nothing); @assertposdef C info) @@ -193,9 +210,11 @@ chol(x::Number, args...) = _chol!(x, nothing) ## No pivoting function cholfact!(A::RealHermSymComplexHerm, ::Type{Val{false}}) if A.uplo == 'U' - Cholesky(_chol!(A.data, UpperTriangular).data, 'U') + CU, info = _chol!(A.data, UpperTriangular) + Cholesky(CU.data, 'U', info) else - Cholesky(_chol!(A.data, LowerTriangular).data, 'L') + CL, info = _chol!(A.data, LowerTriangular) + Cholesky(CL.data, 'L', info) end end @@ -354,14 +373,15 @@ end ## Number function cholfact(x::Number, uplo::Symbol=:U) - xf = fill(chol(x), 1, 1) - Cholesky(xf, uplo) + C, info = _chol!(x, uplo) + xf = fill(C, 1, 1) + Cholesky(xf, uplo, info) end function convert(::Type{Cholesky{T}}, C::Cholesky) where T Cnew = convert(AbstractMatrix{T}, C.factors) - Cholesky{T, typeof(Cnew)}(Cnew, C.uplo) + Cholesky{T, typeof(Cnew)}(Cnew, C.uplo, C.info) end convert(::Type{Factorization{T}}, C::Cholesky{T}) where {T} = C convert(::Type{Factorization{T}}, C::Cholesky) where {T} = convert(Cholesky{T}, C) @@ -386,7 +406,7 @@ convert(::Type{Matrix}, F::CholeskyPivoted) = convert(Array, convert(AbstractArr convert(::Type{Array}, F::CholeskyPivoted) = convert(Matrix, F) full(F::CholeskyPivoted) = convert(AbstractArray, F) -copy(C::Cholesky) = Cholesky(copy(C.factors), C.uplo) +copy(C::Cholesky) = Cholesky(copy(C.factors), C.uplo, C.info) copy(C::CholeskyPivoted) = CholeskyPivoted(copy(C.factors), C.uplo, C.piv, C.rank, C.tol, C.info) size(C::Union{Cholesky, CholeskyPivoted}) = size(C.factors) @@ -417,7 +437,7 @@ show(io::IO, C::Cholesky{<:Any,<:AbstractMatrix}) = (println(io, "$(typeof(C)) with factor:");show(io,C[:UL])) A_ldiv_B!(C::Cholesky{T,<:AbstractMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = - LAPACK.potrs!(C.uplo, C.factors, B) + @assertposdef LAPACK.potrs!(C.uplo, C.factors, B) C.info function A_ldiv_B!(C::Cholesky{<:Any,<:AbstractMatrix}, B::StridedVecOrMat) if C.uplo == 'L' @@ -465,16 +485,18 @@ function A_ldiv_B!(C::CholeskyPivoted, B::StridedMatrix) end function det(C::Cholesky) + C.info == 0 || throw(PosDefException(C.info)) dd = one(real(eltype(C))) - for i in 1:size(C.factors,1) + @inbounds for i in 1:size(C.factors,1) dd *= real(C.factors[i,i])^2 end dd end function logdet(C::Cholesky) + C.info == 0 || throw(PosDefException(C.info)) dd = zero(real(eltype(C))) - for i in 1:size(C.factors,1) + @inbounds for i in 1:size(C.factors,1) dd += log(real(C.factors[i,i])) end dd + dd # instead of 2.0dd which can change the type @@ -505,10 +527,9 @@ function logdet(C::CholeskyPivoted) end inv!(C::Cholesky{<:BlasFloat,<:StridedMatrix}) = - copytri!(LAPACK.potri!(C.uplo, C.factors), C.uplo, true) + @assertposdef copytri!(LAPACK.potri!(C.uplo, C.factors), C.uplo, true) C.info -inv(C::Cholesky{<:BlasFloat,<:StridedMatrix}) = - inv!(copy(C)) +inv(C::Cholesky{<:BlasFloat,<:StridedMatrix}) = inv!(copy(C)) function inv(C::CholeskyPivoted) chkfullrank(C) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index 0f96ffc3ab5dd8..c1dc43965e13b5 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -770,10 +770,12 @@ function factorize(A::StridedMatrix{T}) where T return UpperTriangular(A) end if herm - try - return cholfact(A) + cf = cholfact(A) + if cf.info == 0 + return cf + else + return factorize(Hermitian(A)) end - return factorize(Hermitian(A)) end if sym return factorize(Symmetric(A)) diff --git a/base/linalg/lapack.jl b/base/linalg/lapack.jl index 14d8f76df34ae7..1f9c71488a7737 100644 --- a/base/linalg/lapack.jl +++ b/base/linalg/lapack.jl @@ -2963,10 +2963,10 @@ for (posv, potrf, potri, potrs, pstrf, elty, rtyp) in (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), &uplo, &size(A,1), A, &lda, info) chkargsok(info[]) - #info[1]>0 means the leading minor of order info[i] is not positive definite + #info[] > 0 means the leading minor of order info[] is not positive definite #ordinarily, throw Exception here, but return error code here #this simplifies isposdef! and factorize - return A, info[] + return A, info[] # info stored in Cholesky end # SUBROUTINE DPOTRI( UPLO, N, A, LDA, INFO ) diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index 94a6cb0b7e0a8f..0fce02cbb699fb 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -7,7 +7,6 @@ matprod(x, y) = x*y + x*y # multiply by diagonal matrix as vector function scale!(C::AbstractMatrix, A::AbstractMatrix, b::AbstractVector) m, n = size(A) - p, q = size(C) if size(A) != size(C) throw(DimensionMismatch("size of A, $(size(A)), does not match size of C, $(size(C))")) end @@ -25,7 +24,6 @@ end function scale!(C::AbstractMatrix, b::AbstractVector, A::AbstractMatrix) m, n = size(A) - p, q = size(C) if size(A) != size(C) throw(DimensionMismatch("size of A, $(size(A)), does not match size of C, $(size(C))")) end diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index 2d6d723adefe10..13aa153575f1e7 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -226,8 +226,8 @@ The returned object `F` stores the factorization in a packed format: - if `pivot == Val{true}` then `F` is a [`QRPivoted`](@ref) object, - - otherwise if the element type of `A` is a BLAS type (`Float32`, `Float64`, `Complex64` - or `Complex128`), then `F` is a [`QRCompactWY`](@ref) object, + - otherwise if the element type of `A` is a BLAS type ([`Float32`](@ref), [`Float64`](@ref), + `Complex64` or `Complex128`), then `F` is a [`QRCompactWY`](@ref) object, - otherwise `F` is a [`QR`](@ref) object. diff --git a/base/linalg/svd.jl b/base/linalg/svd.jl index 4ea9291873a898..639d528a1b8123 100644 --- a/base/linalg/svd.jl +++ b/base/linalg/svd.jl @@ -15,10 +15,6 @@ SVD(U::AbstractArray{T}, S::Vector{Tr}, Vt::AbstractArray{T}) where {T,Tr} = SVD `svdfact!` is the same as [`svdfact`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. - -If `thin=true` (default), a thin SVD is returned. For a ``M \\times N`` matrix -`A`, `U` is ``M \\times M`` for a full SVD (`thin=false`) and -``M \\times \\min(M, N)`` for a thin SVD. """ function svdfact!(A::StridedMatrix{T}; thin::Bool=true) where T<:BlasFloat m,n = size(A) @@ -38,6 +34,7 @@ Compute the singular value decomposition (SVD) of `A` and return an `SVD` object `U`, `S`, `V` and `Vt` can be obtained from the factorization `F` with `F[:U]`, `F[:S]`, `F[:V]` and `F[:Vt]`, such that `A = U*diagm(S)*Vt`. The algorithm produces `Vt` and hence `Vt` is more efficient to extract than `V`. +The singular values in `S` are sorted in descending order. If `thin=true` (default), a thin SVD is returned. For a ``M \\times N`` matrix `A`, `U` is ``M \\times M`` for a full SVD (`thin=false`) and @@ -74,7 +71,7 @@ svdfact(x::Integer; thin::Bool=true) = svdfact(float(x), thin=thin) svd(A, thin::Bool=true) -> U, S, V Computes the SVD of `A`, returning `U`, vector `S`, and `V` such that -`A == U*diagm(S)*V'`. +`A == U*diagm(S)*V'`. The singular values in `S` are sorted in descending order. If `thin=true` (default), a thin SVD is returned. For a ``M \\times N`` matrix `A`, `U` is ``M \\times M`` for a full SVD (`thin=false`) and @@ -136,7 +133,7 @@ svdvals(A::AbstractMatrix{<:BlasFloat}) = svdvals!(copy(A)) """ svdvals(A) -Returns the singular values of `A`. +Returns the singular values of `A` in descending order. # Example diff --git a/base/linalg/uniformscaling.jl b/base/linalg/uniformscaling.jl index 92f1c81434d58d..81a3ee1e6b29cf 100644 --- a/base/linalg/uniformscaling.jl +++ b/base/linalg/uniformscaling.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license import Base: copy, ctranspose, getindex, show, transpose, one, zero, inv, - @_pure_meta, hcat, vcat, hvcat + hcat, vcat, hvcat import Base.LinAlg: SingularException struct UniformScaling{T<:Number} @@ -201,7 +201,7 @@ promote_to_arrays(n,k, ::Type{T}, A, B, C) where {T} = (promote_to_arrays_(n[k], T, A), promote_to_arrays_(n[k+1], T, B), promote_to_arrays_(n[k+2], T, C)) promote_to_arrays(n,k, ::Type{T}, A, B, Cs...) where {T} = (promote_to_arrays_(n[k], T, A), promote_to_arrays_(n[k+1], T, B), promote_to_arrays(n,k+2, T, Cs...)...) -promote_to_array_type(A::Tuple{Vararg{Union{AbstractVecOrMat,UniformScaling}}}) = (@_pure_meta; Matrix) +promote_to_array_type(A::Tuple{Vararg{Union{AbstractVecOrMat,UniformScaling}}}) = Matrix for (f,dim,name) in ((:hcat,1,"rows"), (:vcat,2,"cols")) @eval begin diff --git a/base/loading.jl b/base/loading.jl index 201b483ace14f5..18c4765790531e 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -538,24 +538,6 @@ function source_dir() p === nothing ? pwd() : dirname(p) end -""" - @__FILE__ -> AbstractString - -`@__FILE__` expands to a string with the absolute file path of the file containing the -macro. Returns `nothing` if run from a REPL or an empty string if evaluated by -`julia -e `. Alternatively see [`PROGRAM_FILE`](@ref). -""" -macro __FILE__() source_path() end - -""" - @__DIR__ -> AbstractString - -`@__DIR__` expands to a string with the directory part of the absolute path of the file -containing the macro. Returns the current working directory if run from a REPL or if -evaluated by `julia -e `. -""" -macro __DIR__() source_dir() end - include_from_node1(path::AbstractString) = include_from_node1(String(path)) function include_from_node1(_path::String) path, prev = _include_dependency(_path) @@ -823,3 +805,38 @@ function stale_cachefile(modpath::String, cachefile::String) close(io) end end + +""" + @__LINE__ -> Int + +`@__LINE__` expands to the line number of the location of the macrocall. +Returns `0` if the line number could not be determined. +""" +macro __LINE__() + return __source__.line +end + +""" + @__FILE__ -> AbstractString + +`@__FILE__` expands to a string with the path to the file containing the +macrocall, or an empty string if evaluated by `julia -e `. +Returns `nothing` if the macro was missing parser source information. +Alternatively see [`PROGRAM_FILE`](@ref). +""" +macro __FILE__() + __source__.file === nothing && return nothing + return String(__source__.file) +end + +""" + @__DIR__ -> AbstractString + +`@__DIR__` expands to a string with the absolute path to the directory of the file +containing the macrocall. +Returns the current working directory if run from a REPL or if evaluated by `julia -e `. +""" +macro __DIR__() + __source__.file === nothing && return nothing + return abspath(dirname(String(__source__.file))) +end diff --git a/base/markdown/Markdown.jl b/base/markdown/Markdown.jl index d32ae9fa8d983d..fff30da7fec3ca 100644 --- a/base/markdown/Markdown.jl +++ b/base/markdown/Markdown.jl @@ -37,25 +37,23 @@ function mdexpr(s, flavor = :julia) esc(toexpr(md)) end -function docexpr(s, flavor = :julia) - quote - let md = $(mdexpr(s, flavor)) - md.meta[:path] = @__FILE__ - md.meta[:module] = current_module() - md - end - end +function docexpr(source::LineNumberNode, s, flavor = :julia) + :($doc_str($(mdexpr(s, flavor)), $(QuoteNode(source)))) end macro md_str(s, t...) mdexpr(s, t...) end -doc_str(md, file, mod) = (md.meta[:path] = file; md.meta[:module] = mod; md) -doc_str(md::AbstractString, file, mod) = doc_str(parse(md), file, mod) +function doc_str(md, source::LineNumberNode) + md.meta[:path] = isa(source.file, Symbol) ? String(source.file) : "" + md.meta[:module] = current_module() + md +end +doc_str(md::AbstractString, source::LineNumberNode) = doc_str(parse(md), source) macro doc_str(s::AbstractString, t...) - :($(doc_str)($(mdexpr(s, t...)), $(Base).@__FILE__, $(current_module)())) + docexpr(__source__, s, t...) end function Base.display(d::Base.REPL.REPLDisplay, md::Vector{MD}) diff --git a/base/math.jl b/base/math.jl index b5f691990574be..c033f2d8e8efd8 100644 --- a/base/math.jl +++ b/base/math.jl @@ -124,7 +124,7 @@ macro evalpoly(z, p...) :(s = muladd(x, x, y*y)), as..., :(muladd($ai, tt, $b))) - R = Expr(:macrocall, Symbol("@horner"), :tt, map(esc, p)...) + R = Expr(:macrocall, Symbol("@horner"), (), :tt, map(esc, p)...) :(let tt = $(esc(z)) isa(tt, Complex) ? $C : $R end) @@ -161,7 +161,8 @@ log(b::T, x::T) where {T<:Number} = log(x)/log(b) """ log(b,x) -Compute the base `b` logarithm of `x`. Throws [`DomainError`](@ref) for negative `Real` arguments. +Compute the base `b` logarithm of `x`. Throws [`DomainError`](@ref) for negative +[`Real`](@ref) arguments. ```jldoctest julia> log(4,8) @@ -351,8 +352,8 @@ atanh(x) """ log(x) -Compute the natural logarithm of `x`. Throws [`DomainError`](@ref) for negative `Real` arguments. -Use complex negative arguments to obtain complex results. +Compute the natural logarithm of `x`. Throws [`DomainError`](@ref) for negative +[`Real`](@ref) arguments. Use complex negative arguments to obtain complex results. There is an experimental variant in the `Base.Math.JuliaLibm` module, which is typically faster and more accurate. @@ -362,7 +363,8 @@ log(x) """ log2(x) -Compute the logarithm of `x` to base 2. Throws [`DomainError`](@ref) for negative `Real` arguments. +Compute the logarithm of `x` to base 2. Throws [`DomainError`](@ref) for negative +[`Real`](@ref) arguments. # Example ```jldoctest @@ -379,7 +381,7 @@ log2(x) log10(x) Compute the logarithm of `x` to base 10. -Throws [`DomainError`](@ref) for negative `Real` arguments. +Throws [`DomainError`](@ref) for negative [`Real`](@ref) arguments. # Example ```jldoctest @@ -395,7 +397,8 @@ log10(x) """ log1p(x) -Accurate natural logarithm of `1+x`. Throws [`DomainError`](@ref) for `Real` arguments less than -1. +Accurate natural logarithm of `1+x`. Throws [`DomainError`](@ref) for [`Real`](@ref) +arguments less than -1. There is an experimental variant in the `Base.Math.JuliaLibm` module, which is typically faster and more accurate. @@ -438,8 +441,8 @@ sqrt(x::Float32) = sqrt_llvm(x) """ sqrt(x) -Return ``\\sqrt{x}``. Throws [`DomainError`](@ref) for negative `Real` arguments. Use complex -negative arguments instead. The prefix operator `√` is equivalent to `sqrt`. +Return ``\\sqrt{x}``. Throws [`DomainError`](@ref) for negative [`Real`](@ref) arguments. +Use complex negative arguments instead. The prefix operator `√` is equivalent to `sqrt`. """ sqrt(x::Real) = sqrt(float(x)) @@ -459,7 +462,7 @@ julia> √(a^2 + a^2) # a^2 overflows ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). Stacktrace: - [1] sqrt(::Int64) at ./math.jl:431 + [1] sqrt(::Int64) at ./math.jl:447 ``` """ hypot(x::Number, y::Number) = hypot(promote(x, y)...) diff --git a/base/mpfr.jl b/base/mpfr.jl index 4855ca49096785..40e0fd59cf0ac0 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -43,23 +43,9 @@ const DEFAULT_PRECISION = [256] # Basic type and initialization definitions """ - BigFloat(x) - -Create an arbitrary precision floating point number. `x` may be an `Integer`, a `Float64` or -a `BigInt`. The usual mathematical operators are defined for this type, and results are -promoted to a `BigFloat`. - -Note that because decimal literals are converted to floating point numbers when parsed, -`BigFloat(2.1)` may not yield what you expect. You may instead prefer to initialize -constants from strings via [`parse`](@ref), or using the `big` string literal. + BigFloat <: AbstractFloat -```jldoctest -julia> BigFloat(2.1) -2.100000000000000088817841970012523233890533447265625000000000000000000000000000 - -julia> big"2.1" -2.099999999999999999999999999999999999999999999999999999999999999999999999999986 -``` +Arbitrary precision floating point number type. """ mutable struct BigFloat <: AbstractFloat prec::Clong @@ -81,6 +67,27 @@ mutable struct BigFloat <: AbstractFloat end end +""" + BigFloat(x) + +Create an arbitrary precision floating point number. `x` may be an [`Integer`](@ref), a +[`Float64`](@ref) or a [`BigInt`](@ref). The usual mathematical operators are defined for +this type, and results are promoted to a [`BigFloat`](@ref). + +Note that because decimal literals are converted to floating point numbers when parsed, +`BigFloat(2.1)` may not yield what you expect. You may instead prefer to initialize +constants from strings via [`parse`](@ref), or using the `big` string literal. + +```jldoctest +julia> BigFloat(2.1) +2.100000000000000088817841970012523233890533447265625000000000000000000000000000 + +julia> big"2.1" +2.099999999999999999999999999999999999999999999999999999999999999999999999999986 +``` +""" +BigFloat(x) + widen(::Type{Float64}) = BigFloat widen(::Type{BigFloat}) = BigFloat @@ -126,7 +133,7 @@ float(::Type{BigInt}) = BigFloat """ BigFloat(x, prec::Int) -Create a representation of `x` as a `BigFloat` with precision `prec`. +Create a representation of `x` as a [`BigFloat`](@ref) with precision `prec`. """ function BigFloat(x, prec::Int) setprecision(BigFloat, prec) do @@ -137,7 +144,8 @@ end """ BigFloat(x, prec::Int, rounding::RoundingMode) -Create a representation of `x` as a `BigFloat` with precision `prec` and rounding mode `rounding`. +Create a representation of `x` as a [`BigFloat`](@ref) with precision `prec` and +rounding mode `rounding`. """ function BigFloat(x, prec::Int, rounding::RoundingMode) setrounding(BigFloat, rounding) do @@ -148,7 +156,8 @@ end """ BigFloat(x, rounding::RoundingMode) -Create a representation of `x` as a `BigFloat` with the current global precision and rounding mode `rounding`. +Create a representation of `x` as a [`BigFloat`](@ref) with the current global precision +and rounding mode `rounding`. """ function BigFloat(x::Union{Integer, AbstractFloat, String}, rounding::RoundingMode) BigFloat(x, precision(BigFloat), rounding) @@ -157,7 +166,7 @@ end """ BigFloat(x::String) -Create a representation of the string `x` as a `BigFloat`. +Create a representation of the string `x` as a [`BigFloat`](@ref). """ BigFloat(x::String) = parse(BigFloat, x) @@ -721,7 +730,7 @@ end """ precision(BigFloat) -Get the precision (in bits) currently used for `BigFloat` arithmetic. +Get the precision (in bits) currently used for [`BigFloat`](@ref) arithmetic. """ precision(::Type{BigFloat}) = DEFAULT_PRECISION[end] # precision of the type BigFloat itself diff --git a/base/number.jl b/base/number.jl index 704bf42fc00700..d34f3ba10a438b 100644 --- a/base/number.jl +++ b/base/number.jl @@ -190,8 +190,8 @@ _default_type(::Type{Number}) = Int """ factorial(n) -Factorial of `n`. If `n` is an `Integer`, the factorial is computed as an -integer (promoted to at least 64 bits). Note that this may overflow if `n` is not small, +Factorial of `n`. If `n` is an [`Integer`](@ref), the factorial is computed as an +integer (promoted to at least 64 bits). Note that this may overflow if `n` is not small, but you can use `factorial(big(n))` to compute the result exactly in arbitrary precision. If `n` is not an `Integer`, `factorial(n)` is equivalent to [`gamma(n+1)`](@ref). diff --git a/base/operators.jl b/base/operators.jl index bbec5c09e28f32..47ac4b25de3ea9 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -532,8 +532,8 @@ Unsigned right bit shift operator, `x >>> n`. For `n >= 0`, the result is `x` shifted right by `n` bits, where `n >= 0`, filling with `0`s. For `n < 0`, this is equivalent to `x << -n`. -For `Unsigned` integer types, this is equivalent to [`>>`](@ref). For -`Signed` integer types, this is equivalent to `signed(unsigned(x) >> n)`. +For [`Unsigned`](@ref) integer types, this is equivalent to [`>>`](@ref). For +[`Signed`](@ref) integer types, this is equivalent to `signed(unsigned(x) >> n)`. ```jldoctest julia> Int8(-14) >>> 2 @@ -545,7 +545,8 @@ julia> bits(Int8(-14)) julia> bits(Int8(60)) "00111100" ``` -`BigInt`s are treated as if having infinite size, so no filling is required and this + +[`BigInt`](@ref)s are treated as if having infinite size, so no filling is required and this is equivalent to [`>>`](@ref). See also [`>>`](@ref), [`<<`](@ref). diff --git a/base/precompile.jl b/base/precompile.jl index 9bd0f90f30572f..5149aed65b3324 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -743,7 +743,7 @@ precompile(Tuple{getfield(Base.Docs, Symbol("#@repl")), Base.TTY, Symbol}) precompile(Tuple{typeof(Base.Docs.repl), Base.TTY, Symbol}) precompile(Tuple{typeof(Base.Docs._repl), Symbol}) precompile(Tuple{getfield(Core, Symbol("#@doc")), Symbol}) -precompile(Tuple{typeof(Base.Docs.docm), Symbol}) +precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Symbol}) precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Base.Markdown.Config, Symbol, Int64}) precompile(Tuple{Type{Base.Markdown.MD}}) precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Base.Markdown.Config, Symbol}) @@ -1720,8 +1720,8 @@ precompile(Tuple{typeof(Base.Distributed.send_msg), Base.Distributed.Worker, Bas precompile(Tuple{typeof(Base.Distributed.send_msg_), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.RemoteDoMsg, Bool}) precompile(Tuple{typeof(Base.Distributed.terminate_all_workers)}) precompile(Tuple{typeof(Base.Distributed.test_existing_ref), Base.Distributed.Future}) -precompile(Tuple{typeof(Base.Docs.docm), String, Expr}) -precompile(Tuple{typeof(Base.Docs.docm), String, Expr, Bool}) +precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, String, Expr}) +precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, String, Expr, Bool}) precompile(Tuple{typeof(Base.Docs.keyworddoc), String, Base.BaseDocs.Keyword}) precompile(Tuple{typeof(Base.Docs.objectdoc), String, Expr, Expr, Expr}) precompile(Tuple{typeof(Base.FastMath.make_fastmath), Expr}) diff --git a/base/printf.jl b/base/printf.jl index 48ead94958f590..b743ab6e05529f 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license module Printf -using Base.Grisu +using Base: Grisu, GMP export @printf, @sprintf ### printf formatter generation ### @@ -1128,10 +1128,12 @@ function bigfloat_printf(out, d, flags::String, width::Int, precision::Int, c::C write(fmt, UInt8(0)) printf_fmt = take!(fmt) @assert length(printf_fmt) == fmt_len - bufsiz = length(DIGITS) - 1 - lng = ccall((:mpfr_snprintf,:libmpfr), Int32, (Ptr{UInt8}, Culong, Ptr{UInt8}, Ptr{BigFloat}...), DIGITS, bufsiz, printf_fmt, &d) + bufsiz = length(DIGITS) + lng = ccall((:mpfr_snprintf,:libmpfr), Int32, + (Ptr{UInt8}, Culong, Ptr{UInt8}, Ptr{BigFloat}...), + DIGITS, bufsiz, printf_fmt, &d) lng > 0 || error("invalid printf formatting for BigFloat") - unsafe_write(out, pointer(DIGITS), min(lng,bufsiz)) + unsafe_write(out, pointer(DIGITS), min(lng, bufsiz-1)) return (false, ()) end diff --git a/base/promotion.jl b/base/promotion.jl index 4fbe3f7068a2c3..2972a7da99cce2 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -122,14 +122,14 @@ end ## promotion mechanism ## -promote_type() = (@_pure_meta; Bottom) -promote_type(T) = (@_pure_meta; T) -promote_type(T, S, U, V...) = (@_pure_meta; promote_type(T, promote_type(S, U, V...))) +promote_type() = Bottom +promote_type(T) = T +promote_type(T, S, U, V...) = (@_inline_meta; promote_type(T, promote_type(S, U, V...))) -promote_type(::Type{Bottom}, ::Type{Bottom}) = (@_pure_meta; Bottom) -promote_type(::Type{T}, ::Type{T}) where {T} = (@_pure_meta; T) -promote_type(::Type{T}, ::Type{Bottom}) where {T} = (@_pure_meta; T) -promote_type(::Type{Bottom}, ::Type{T}) where {T} = (@_pure_meta; T) +promote_type(::Type{Bottom}, ::Type{Bottom}) = Bottom +promote_type(::Type{T}, ::Type{T}) where {T} = T +promote_type(::Type{T}, ::Type{Bottom}) where {T} = T +promote_type(::Type{Bottom}, ::Type{T}) where {T} = T """ promote_type(type1, type2) @@ -137,8 +137,8 @@ promote_type(::Type{Bottom}, ::Type{T}) where {T} = (@_pure_meta; T) Determine a type big enough to hold values of each argument type without loss, whenever possible. In some cases, where no type exists to which both types can be promoted losslessly, some loss is tolerated; for example, `promote_type(Int64, Float64)` returns -`Float64` even though strictly, not all `Int64` values can be represented exactly as -`Float64` values. +[`Float64`](@ref) even though strictly, not all [`Int64`](@ref) values can be represented +exactly as `Float64` values. ```jldoctest julia> promote_type(Int64, Float64) @@ -152,7 +152,7 @@ BigFloat ``` """ function promote_type(::Type{T}, ::Type{S}) where {T,S} - @_pure_meta + @_inline_meta # Try promote_rule in both orders. Typically only one is defined, # and there is a fallback returning Bottom below, so the common case is # promote_type(T, S) => @@ -161,26 +161,29 @@ function promote_type(::Type{T}, ::Type{S}) where {T,S} promote_result(T, S, promote_rule(T,S), promote_rule(S,T)) end -promote_rule(T, S) = (@_pure_meta; Bottom) +promote_rule(::Type{<:Any}, ::Type{<:Any}) = Bottom -promote_result(t,s,T,S) = (@_pure_meta; promote_type(T,S)) +promote_result(::Type{<:Any},::Type{<:Any},::Type{T},::Type{S}) where {T,S} = (@_inline_meta; promote_type(T,S)) # If no promote_rule is defined, both directions give Bottom. In that # case use typejoin on the original types instead. -promote_result(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) where {T,S} = (@_pure_meta; typejoin(T, S)) +promote_result(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) where {T,S} = (@_inline_meta; typejoin(T, S)) promote() = () promote(x) = (x,) function promote(x::T, y::S) where {T,S} + @_inline_meta (convert(promote_type(T,S),x), convert(promote_type(T,S),y)) end -promote_typeof(x) = (@_pure_meta; typeof(x)) -promote_typeof(x, xs...) = (@_pure_meta; promote_type(typeof(x), promote_typeof(xs...))) +promote_typeof(x) = typeof(x) +promote_typeof(x, xs...) = (@_inline_meta; promote_type(typeof(x), promote_typeof(xs...))) function promote(x, y, z) + @_inline_meta (convert(promote_typeof(x,y,z), x), convert(promote_typeof(x,y,z), y), convert(promote_typeof(x,y,z), z)) end function promote(x, y, zs...) + @_inline_meta (convert(promote_typeof(x,y,zs...), x), convert(promote_typeof(x,y,zs...), y), convert(Tuple{Vararg{promote_typeof(x,y,zs...)}}, zs)...) @@ -195,16 +198,16 @@ end # happens, and +(promote(x,y)...) is called again, causing a stack # overflow. function promote_result(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) where {T<:Number,S<:Number} - @_pure_meta + @_inline_meta promote_to_supertype(T, S, typejoin(T,S)) end # promote numeric types T and S to typejoin(T,S) if T<:S or S<:T # for example this makes promote_type(Integer,Real) == Real without # promoting arbitrary pairs of numeric types to Number. -promote_to_supertype(::Type{T}, ::Type{T}, ::Type{T}) where {T<:Number} = (@_pure_meta; T) -promote_to_supertype(::Type{T}, ::Type{S}, ::Type{T}) where {T<:Number,S<:Number} = (@_pure_meta; T) -promote_to_supertype(::Type{T}, ::Type{S}, ::Type{S}) where {T<:Number,S<:Number} = (@_pure_meta; S) +promote_to_supertype(::Type{T}, ::Type{T}, ::Type{T}) where {T<:Number} = (@_inline_meta; T) +promote_to_supertype(::Type{T}, ::Type{S}, ::Type{T}) where {T<:Number,S<:Number} = (@_inline_meta; T) +promote_to_supertype(::Type{T}, ::Type{S}, ::Type{S}) where {T<:Number,S<:Number} = (@_inline_meta; S) promote_to_supertype(::Type{T}, ::Type{S}, ::Type) where {T<:Number,S<:Number} = error("no promotion exists for ", T, " and ", S) @@ -304,7 +307,7 @@ minmax(x::Real, y::Real) = minmax(promote(x, y)...) # "Promotion" that takes a function into account and tries to preserve # non-concrete types. These are meant to be used mainly by elementwise # operations, so it is advised against overriding them -_default_type(T::Type) = (@_pure_meta; T) +_default_type(T::Type) = (@_inline_meta; T) if isdefined(Core, :Inference) const _return_type = Core.Inference.return_type @@ -312,7 +315,7 @@ else _return_type(f::ANY, t::ANY) = Any end -promote_op(::Any...) = (@_pure_meta; Any) +promote_op(::Any...) = (@_inline_meta; Any) function promote_op{S}(f, ::Type{S}) @_inline_meta T = _return_type(f, Tuple{_default_type(S)}) diff --git a/base/random.jl b/base/random.jl index 3697302a05153b..7d15e802b678ad 100644 --- a/base/random.jl +++ b/base/random.jl @@ -221,8 +221,8 @@ end Reseed the random number generator. If a `seed` is provided, the RNG will give a reproducible sequence of numbers, otherwise Julia will get entropy from the system. For -`MersenneTwister`, the `seed` may be a non-negative integer or a vector of `UInt32` integers. -`RandomDevice` does not support seeding. +`MersenneTwister`, the `seed` may be a non-negative integer or a vector of [`UInt32`](@ref) +integers. `RandomDevice` does not support seeding. """ srand(r::MersenneTwister) = srand(r, make_seed()) srand(r::MersenneTwister, n::Integer) = srand(r, make_seed(n)) @@ -257,10 +257,22 @@ globalRNG() = GLOBAL_RNG Pick a random element or array of random elements from the set of values specified by `S`; `S` can be * an indexable collection (for example `1:n` or `['x','y','z']`), or +* a `Dict`, a `Set` or an `IntSet`, or * a type: the set of values to pick from is then equivalent to `typemin(S):typemax(S)` for - integers (this is not applicable to `BigInt`), and to ``[0, 1)`` for floating point numbers; + integers (this is not applicable to [`BigInt`](@ref)), and to ``[0, 1)`` for floating + point numbers; -`S` defaults to `Float64`. +`S` defaults to [`Float64`](@ref). + +```julia-repl +julia> rand(Int, 2) +2-element Array{Int64,1}: + 1339893410598768192 + 1575814717733606317 + +julia> rand(MersenneTwister(0), Dict(1=>2, 3=>4)) +1=>2 +``` """ @inline rand() = rand(GLOBAL_RNG, CloseOpen) @inline rand(T::Type) = rand(GLOBAL_RNG, T) @@ -275,7 +287,7 @@ rand(r::AbstractArray) = rand(GLOBAL_RNG, r) """ rand!([rng=GLOBAL_RNG], A, [coll]) -Populate the array `A` with random values. If the indexable collection `coll` is specified, +Populate the array `A` with random values. If the collection `coll` is specified, the values are picked randomly from `coll`. This is equivalent to `copy!(A, rand(rng, coll, size(A)))` or `copy!(A, rand(rng, eltype(A), size(A)))` but without allocating a new array. """ @@ -338,19 +350,33 @@ function rand(r::AbstractRNG, ::Type{Char}) (c < 0xd800) ? Char(c) : Char(c+0x800) end -# random values from Dict or Set (for efficiency) +# random values from Dict, Set, IntSet (for efficiency) function rand(r::AbstractRNG, t::Dict) - isempty(t) && throw(ArgumentError("dict must be non-empty")) - n = length(t.slots) + isempty(t) && throw(ArgumentError("collection must be non-empty")) + rg = RangeGenerator(1:length(t.slots)) while true - i = rand(r, 1:n) - Base.isslotfilled(t, i) && return (t.keys[i] => t.vals[i]) + i = rand(r, rg) + Base.isslotfilled(t, i) && @inbounds return (t.keys[i] => t.vals[i]) end end rand(t::Dict) = rand(GLOBAL_RNG, t) rand(r::AbstractRNG, s::Set) = rand(r, s.dict).first rand(s::Set) = rand(GLOBAL_RNG, s) +function rand(r::AbstractRNG, s::IntSet) + isempty(s) && throw(ArgumentError("collection must be non-empty")) + # s can be empty while s.bits is not, so we cannot rely on the + # length check in RangeGenerator below + rg = RangeGenerator(1:length(s.bits)) + while true + n = rand(r, rg) + @inbounds b = s.bits[n] + b && return n + end +end + +rand(s::IntSet) = rand(GLOBAL_RNG, s) + ## Arrays of random numbers rand(r::AbstractRNG, dims::Dims) = rand(r, Float64, dims) @@ -369,6 +395,22 @@ function rand!{T}(r::AbstractRNG, A::AbstractArray{T}) A end +function rand!(r::AbstractRNG, A::AbstractArray, s::Union{Dict,Set,IntSet}) + for i in eachindex(A) + @inbounds A[i] = rand(r, s) + end + A +end + +rand!(A::AbstractArray, s::Union{Dict,Set,IntSet}) = rand!(GLOBAL_RNG, A, s) + +rand(r::AbstractRNG, s::Dict{K,V}, dims::Dims) where {K,V} = rand!(r, Array{Pair{K,V}}(dims), s) +rand(r::AbstractRNG, s::Set{T}, dims::Dims) where {T} = rand!(r, Array{T}(dims), s) +rand(r::AbstractRNG, s::IntSet, dims::Dims) = rand!(r, Array{Int}(dims), s) +rand(r::AbstractRNG, s::Union{Dict,Set,IntSet}, dims::Integer...) = rand(r, s, convert(Dims, dims)) +rand(s::Union{Dict,Set,IntSet}, dims::Integer...) = rand(GLOBAL_RNG, s, dims) +rand(s::Union{Dict,Set,IntSet}, dims::Dims) = rand(GLOBAL_RNG, s, dims) + # MersenneTwister function rand_AbstractArray_Float64!{I<:FloatInterval}(r::MersenneTwister, A::AbstractArray{Float64}, n=length(A), ::Type{I}=CloseOpen) @@ -1181,9 +1223,9 @@ const ziggurat_exp_r = 7.6971174701310497140446280481 Generate a normally-distributed random number of type `T` with mean 0 and standard deviation 1. Optionally generate an array of normally-distributed random numbers. The `Base` module currently provides an implementation for the types -`Float16`, `Float32`, and `Float64` (the default), and their `Complex` counterparts. -When the type argument is complex, the values are drawn from the circularly symmetric -complex normal distribution. +[`Float16`](@ref), [`Float32`](@ref), and [`Float64`](@ref) (the default), and their +[`Complex`](@ref) counterparts. When the type argument is complex, the values are drawn +from the circularly symmetric complex normal distribution. """ @inline function randn(rng::AbstractRNG=GLOBAL_RNG) @inbounds begin @@ -1217,7 +1259,7 @@ end Generate a random number of type `T` according to the exponential distribution with scale 1. Optionally generate an array of such random numbers. The `Base` module currently provides an implementation for the types -`Float16`, `Float32`, and `Float64` (the default). +[`Float16`](@ref), [`Float32`](@ref), and [`Float64`](@ref) (the default). """ @inline function randexp(rng::AbstractRNG=GLOBAL_RNG) @inbounds begin diff --git a/base/rational.jl b/base/rational.jl index 611d7ca5e3252e..b3f901300399ea 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -1,5 +1,10 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +""" + Rational{T<:Integer} <: Real + +Rational number type, with numerator and denominator of type `T`. +""" struct Rational{T<:Integer} <: Real num::T den::T @@ -22,7 +27,7 @@ end """ //(num, den) -Divide two integers or rational numbers, giving a `Rational` result. +Divide two integers or rational numbers, giving a [`Rational`](@ref) result. ```jldoctest julia> 3 // 5 @@ -104,7 +109,7 @@ widen(::Type{Rational{T}}) where {T} = Rational{widen(T)} """ rationalize([T<:Integer=Int,] x; tol::Real=eps(x)) -Approximate floating point number `x` as a `Rational` number with components +Approximate floating point number `x` as a [`Rational`](@ref) number with components of the given integer type. The result will differ from `x` by no more than `tol`. If `T` is not provided, it defaults to `Int`. diff --git a/base/reflection.jl b/base/reflection.jl index 58d9b67e191771..e322a22dfe020a 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -219,8 +219,8 @@ isstructtype(x) = (@_pure_meta; false) isbits(T) Return `true` if `T` is a "plain data" type, meaning it is immutable and contains no -references to other values. Typical examples are numeric types such as `UInt8`, `Float64`, -and `Complex{Float64}`. +references to other values. Typical examples are numeric types such as [`UInt8`](@ref), +[`Float64`](@ref), and [`Complex{Float64}`](@ref). ```jldoctest julia> isbits(Complex{Float64}) @@ -763,7 +763,6 @@ function func_for_method_checked(m::Method, types::ANY) return m end - """ code_typed(f, types; optimize=true) @@ -778,7 +777,7 @@ function code_typed(f::ANY, types::ANY=Tuple; optimize=true) end types = to_tuple_type(types) asts = [] - world = typemax(UInt) + world = ccall(:jl_get_world_counter, UInt, ()) params = Core.Inference.InferenceParams(world) for x in _methods(f, types, -1, world) meth = func_for_method_checked(x[3], types) @@ -796,7 +795,7 @@ function return_types(f::ANY, types::ANY=Tuple) end types = to_tuple_type(types) rt = [] - world = typemax(UInt) + world = ccall(:jl_get_world_counter, UInt, ()) params = Core.Inference.InferenceParams(world) for x in _methods(f, types, -1, world) meth = func_for_method_checked(x[3], types) diff --git a/base/rounding.jl b/base/rounding.jl index 67f71d9dda57d7..bcb9b6328ac15e 100644 --- a/base/rounding.jl +++ b/base/rounding.jl @@ -37,7 +37,7 @@ Currently supported rounding modes are: - [`RoundNearestTiesAway`](@ref) - [`RoundNearestTiesUp`](@ref) - [`RoundToZero`](@ref) -- `RoundFromZero` (`BigFloat` only) +- `RoundFromZero` ([`BigFloat`](@ref) only) - [`RoundUp`](@ref) - [`RoundDown`](@ref) """ @@ -118,9 +118,9 @@ arithmetic functions ([`+`](@ref), [`-`](@ref), [`*`](@ref), functions may give incorrect or invalid values when using rounding modes other than the default `RoundNearest`. -Note that this may affect other types, for instance changing the rounding mode of `Float64` -will change the rounding mode of `Float32`. See [`RoundingMode`](@ref) for -available modes. +Note that this may affect other types, for instance changing the rounding mode of +[`Float64`](@ref) will change the rounding mode of [`Float32`](@ref). +See [`RoundingMode`](@ref) for available modes. !!! warning diff --git a/base/show.jl b/base/show.jl index 3e39b419f284bf..5cfa8acdd032d1 100644 --- a/base/show.jl +++ b/base/show.jl @@ -505,10 +505,6 @@ const prec_decl = operator_precedence(:(::)) is_expr(ex, head::Symbol) = (isa(ex, Expr) && (ex.head == head)) is_expr(ex, head::Symbol, n::Int) = is_expr(ex, head) && length(ex.args) == n -is_linenumber(ex::LineNumberNode) = true -is_linenumber(ex::Expr) = (ex.head == :line) -is_linenumber(ex) = false - is_quoted(ex) = false is_quoted(ex::QuoteNode) = true is_quoted(ex::Expr) = is_expr(ex, :quote, 1) || is_expr(ex, :inert, 1) @@ -522,7 +518,7 @@ typeemphasize(io::IO) = get(io, :TYPEEMPHASIZE, false) === true const indent_width = 4 -function show_expr_type(io::IO, ty, emph) +function show_expr_type(io::IO, ty::ANY, emph::Bool) if ty === Function print(io, "::F") elseif ty === Core.IntrinsicFunction @@ -538,18 +534,22 @@ end emphasize(io, str::AbstractString) = have_color ? print_with_color(Base.error_color(), io, str; bold = true) : print(io, uppercase(str)) -show_linenumber(io::IO, line) = print(io," # line ",line,':') -show_linenumber(io::IO, line, file) = print(io," # ", file,", line ",line,':') +show_linenumber(io::IO, line) = print(io, "#= line ", line, " =#") +show_linenumber(io::IO, line, file) = print(io, "#= ", file, ":", line, " =#") +show_linenumber(io::IO, line, file::Void) = show_linenumber(io, line) # show a block, e g if/for/etc function show_block(io::IO, head, args::Vector, body, indent::Int) - print(io, head, ' ') - show_list(io, args, ", ", indent) + print(io, head) + if !isempty(args) + print(io, ' ') + show_list(io, args, ", ", indent) + end ind = head === :module || head === :baremodule ? indent : indent + indent_width exs = (is_expr(body, :block) || is_expr(body, :body)) ? body.args : Any[body] for ex in exs - if !is_linenumber(ex); print(io, '\n', " "^ind); end + print(io, '\n', " "^ind) show_unquoted(io, ex, ind, -1) end print(io, '\n', " "^indent) @@ -566,7 +566,7 @@ end # show an indented list function show_list(io::IO, items, sep, indent::Int, prec::Int=0, enclose_operators::Bool=false) n = length(items) - if n == 0; return end + n == 0 && return indent += indent_width first = true for item in items @@ -613,7 +613,7 @@ end ## AST printing ## show_unquoted(io::IO, sym::Symbol, ::Int, ::Int) = print(io, sym) -show_unquoted(io::IO, ex::LineNumberNode, ::Int, ::Int) = show_linenumber(io, ex.line) +show_unquoted(io::IO, ex::LineNumberNode, ::Int, ::Int) = show_linenumber(io, ex.line, ex.file) show_unquoted(io::IO, ex::LabelNode, ::Int, ::Int) = print(io, ex.label, ": ") show_unquoted(io::IO, ex::GotoNode, ::Int, ::Int) = print(io, "goto ", ex.label) show_unquoted(io::IO, ex::GlobalRef, ::Int, ::Int) = print(io, ex.mod, '.', ex.name) @@ -627,7 +627,7 @@ function show_unquoted(io::IO, ex::Slot, ::Int, ::Int) if isa(slottypes, Array) && slotid <= length(slottypes::Array) slottype = slottypes[slotid] # The Slot in assignment can somehow have an Any type - if slottype <: typ + if isa(slottype, Type) && isa(typ, Type) && slottype <: typ typ = slottype end end @@ -913,12 +913,20 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) print(io, head, ' ') show_list(io, args, ", ", indent) - elseif head === :macrocall && nargs >= 1 + elseif head === :macrocall && nargs >= 2 + # first show the line number argument as a comment + if isa(args[2], LineNumberNode) || is_expr(args[2], :line) + print(io, args[2], ' ') + end # Use the functional syntax unless specifically designated with prec=-1 + # and hide the line number argument from the argument list if prec >= 0 - show_call(io, :call, ex.args[1], ex.args[2:end], indent) + show_call(io, :call, args[1], args[3:end], indent) else - show_list(io, args, ' ', indent) + show_args = Vector{Any}(length(args) - 1) + show_args[1] = args[1] + show_args[2:end] = args[3:end] + show_list(io, show_args, ' ', indent) end elseif head === :line && 1 <= nargs <= 2 @@ -1562,7 +1570,7 @@ end summary(x) Return a string giving a brief description of a value. By default returns -`string(typeof(x))`, e.g. `Int64`. +`string(typeof(x))`, e.g. [`Int64`](@ref). For arrays, returns a string of size and type info, e.g. `10-element Array{Int64,1}`. diff --git a/base/socket.jl b/base/socket.jl index ae4e055c913254..108624be549174 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -24,7 +24,7 @@ end """ IPv4(host::Integer) -> IPv4 -Returns an IPv4 object from ip address `host` formatted as an `Integer`. +Returns an IPv4 object from ip address `host` formatted as an [`Integer`](@ref). ```jldoctest julia> IPv4(3223256218) @@ -76,7 +76,7 @@ end """ IPv6(host::Integer) -> IPv6 -Returns an IPv6 object from ip address `host` formatted as an `Integer`. +Returns an IPv6 object from ip address `host` formatted as an [`Integer`](@ref). ```jldoctest julia> IPv6(3223256218) diff --git a/base/sparse/abstractsparse.jl b/base/sparse/abstractsparse.jl index 6de3403b5d6de5..e17d3be97dbcbb 100644 --- a/base/sparse/abstractsparse.jl +++ b/base/sparse/abstractsparse.jl @@ -20,4 +20,4 @@ issparse(S::LinAlg.UnitLowerTriangular{<:Any,<:AbstractSparseMatrix}) = true issparse(S::UpperTriangular{<:Any,<:AbstractSparseMatrix}) = true issparse(S::LinAlg.UnitUpperTriangular{<:Any,<:AbstractSparseMatrix}) = true -indtype(S::AbstractSparseArray{<:Any,Ti}) where {Ti} = (Base.@_pure_meta; Ti) +indtype(S::AbstractSparseArray{<:Any,Ti}) where {Ti} = Ti diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index cee5b355164089..bb18c058bb2b46 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -292,7 +292,10 @@ function copy!(A::SparseMatrixCSC, B::SparseMatrixCSC) return A end -similar(S::SparseMatrixCSC, Tv::Type = eltype(S)) = SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), Vector{Tv}(length(S.nzval))) +function similar(S::SparseMatrixCSC, ::Type{Tv} = eltype(S)) where Tv + SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), Vector{Tv}(length(S.nzval))) +end + function similar(S::SparseMatrixCSC, ::Type{Tv}, ::Type{Ti}) where {Tv,Ti} new_colptr = copy!(similar(S.colptr, Ti), S.colptr) new_rowval = copy!(similar(S.rowval, Ti), S.rowval) @@ -827,9 +830,9 @@ information. See also: `unchecked_aliasing_permute!` """ -function unchecked_noalias_permute!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, +function unchecked_noalias_permute!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, - q::AbstractVector{<:Integer}, C::SparseMatrixCSC{Tv,Ti}) + q::AbstractVector{<:Integer}, C::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} halfperm!(C, A, q) _computecolptrs_permute!(X, A, q, X.colptr) _distributevals_halfperm!(X, C, p, identity) @@ -847,9 +850,9 @@ for additional information; these methods are identical but for this method's re the additional `workcolptr`, `length(workcolptr) >= A.n + 1`, which enables efficient handling of the source-destination aliasing. """ -function unchecked_aliasing_permute!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, +function unchecked_aliasing_permute!(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}, - C::SparseMatrixCSC{Tv,Ti}, workcolptr::Vector{Ti}) + C::SparseMatrixCSC{Tv,Ti}, workcolptr::Vector{Ti}) where {Tv,Ti} halfperm!(C, A, q) _computecolptrs_permute!(A, A, q, workcolptr) _distributevals_halfperm!(A, C, p, identity) @@ -861,8 +864,8 @@ Computes `PAQ`'s column pointers, storing them shifted one position forward in ` `_distributevals_halfperm!` fixes this shift. Saves some work relative to `_computecolptrs_halfperm!` as described in `uncheckednoalias_permute!`'s documentation. """ -function _computecolptrs_permute!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, - A::SparseMatrixCSC{Tv,Ti}, q::AbstractVector{<:Integer}, workcolptr::Vector{Ti}) +function _computecolptrs_permute!(X::SparseMatrixCSC{Tv,Ti}, + A::SparseMatrixCSC{Tv,Ti}, q::AbstractVector{<:Integer}, workcolptr::Vector{Ti}) where {Tv,Ti} # Compute `A[p,q]`'s column counts. Store shifted forward one position in workcolptr. @inbounds for k in 1:A.n workcolptr[k+1] = A.colptr[q[k] + 1] - A.colptr[q[k]] @@ -898,9 +901,9 @@ end Helper method for `permute` and `permute!` methods operating on `SparseMatrixCSC`s. Checks whether row- and column- permutation arguments `p` and `q` are valid permutations. """ -function _checkargs_permutationsvalid_permute!{Ti<:Integer}( +function _checkargs_permutationsvalid_permute!( p::AbstractVector{<:Integer}, pcheckspace::Vector{Ti}, - q::AbstractVector{<:Integer}, qcheckspace::Vector{Ti}) + q::AbstractVector{<:Integer}, qcheckspace::Vector{Ti}) where Ti<:Integer if !_ispermutationvalid_permute!(p, pcheckspace) throw(ArgumentError("row-permutation argument `p` must be a valid permutation")) elseif !_ispermutationvalid_permute!(q, qcheckspace) @@ -1000,42 +1003,42 @@ and `unchecked_aliasing_permute!`. See also: [`permute`](@ref) """ -function permute!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, - p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}) +function permute!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, + p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}) where {Tv,Ti} _checkargs_sourcecompatdest_permute!(A, X) _checkargs_sourcecompatperms_permute!(A, p, q) C = SparseMatrixCSC(A.n, A.m, Vector{Ti}(A.m + 1), Vector{Ti}(nnz(A)), Vector{Tv}(nnz(A))) _checkargs_permutationsvalid_permute!(p, C.colptr, q, X.colptr) unchecked_noalias_permute!(X, A, p, q, C) end -function permute!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, +function permute!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}, - C::SparseMatrixCSC{Tv,Ti}) + C::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} _checkargs_sourcecompatdest_permute!(A, X) _checkargs_sourcecompatperms_permute!(A, p, q) _checkargs_sourcecompatworkmat_permute!(A, C) _checkargs_permutationsvalid_permute!(p, C.colptr, q, X.colptr) unchecked_noalias_permute!(X, A, p, q, C) end -function permute!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, - q::AbstractVector{<:Integer}) +function permute!(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, + q::AbstractVector{<:Integer}) where {Tv,Ti} _checkargs_sourcecompatperms_permute!(A, p, q) C = SparseMatrixCSC(A.n, A.m, Vector{Ti}(A.m + 1), Vector{Ti}(nnz(A)), Vector{Tv}(nnz(A))) workcolptr = Vector{Ti}(A.n + 1) _checkargs_permutationsvalid_permute!(p, C.colptr, q, workcolptr) unchecked_aliasing_permute!(A, p, q, C, workcolptr) end -function permute!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, - q::AbstractVector{<:Integer}, C::SparseMatrixCSC{Tv,Ti}) +function permute!(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, + q::AbstractVector{<:Integer}, C::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} _checkargs_sourcecompatperms_permute!(A, p, q) _checkargs_sourcecompatworkmat_permute!(A, C) workcolptr = Vector{Ti}(A.n + 1) _checkargs_permutationsvalid_permute!(p, C.colptr, q, workcolptr) unchecked_aliasing_permute!(A, p, q, C, workcolptr) end -function permute!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, +function permute!(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}, C::SparseMatrixCSC{Tv,Ti}, - workcolptr::Vector{Ti}) + workcolptr::Vector{Ti}) where {Tv,Ti} _checkargs_sourcecompatperms_permute!(A, p, q) _checkargs_sourcecompatworkmat_permute!(A, C) _checkargs_sourcecompatworkcolptr_permute!(A, workcolptr) @@ -1052,8 +1055,8 @@ row count (`length(p) == A.m`). For expert drivers and additional information, see [`permute!`](@ref). """ -function permute{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, - q::AbstractVector{<:Integer}) +function permute(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, + q::AbstractVector{<:Integer}) where {Tv,Ti} _checkargs_sourcecompatperms_permute!(A, p, q) X = SparseMatrixCSC(A.m, A.n, Vector{Ti}(A.n + 1), Vector{Ti}(nnz(A)), Vector{Tv}(nnz(A))) C = SparseMatrixCSC(A.n, A.m, Vector{Ti}(A.m + 1), Vector{Ti}(nnz(A)), Vector{Tv}(nnz(A))) @@ -1273,8 +1276,8 @@ julia> sprand(rng, Float64, 3, 0.75) [3] = 0.298614 ``` """ -function sprand{T}(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat, - rfn::Function, ::Type{T}=eltype(rfn(r,1))) +function sprand(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat, + rfn::Function, ::Type{T}=eltype(rfn(r,1))) where T N = m*n N == 0 && return spzeros(T,m,n) N == 1 && return rand(r) <= density ? sparse([1], [1], rfn(r,1)) : spzeros(T,1,1) @@ -1283,8 +1286,8 @@ function sprand{T}(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloa sparse_IJ_sorted!(I, J, rfn(r,length(I)), m, n, +) # it will never need to combine end -function sprand{T}(m::Integer, n::Integer, density::AbstractFloat, - rfn::Function, ::Type{T}=eltype(rfn(1))) +function sprand(m::Integer, n::Integer, density::AbstractFloat, + rfn::Function, ::Type{T}=eltype(rfn(1))) where T N = m*n N == 0 && return spzeros(T,m,n) N == 1 && return rand() <= density ? sparse([1], [1], rfn(1)) : spzeros(T,1,1) @@ -1357,7 +1360,7 @@ spones(S::SparseMatrixCSC{T}) where {T} = Create a sparse vector of length `m` or sparse matrix of size `m x n`. This sparse array will not contain any nonzero values. No storage will be allocated -for nonzero values during construction. The type defaults to `Float64` if not +for nonzero values during construction. The type defaults to [`Float64`](@ref) if not specified. ```jldoctest @@ -1369,16 +1372,18 @@ julia> spzeros(Float32, 4) ``` """ spzeros(m::Integer, n::Integer) = spzeros(Float64, m, n) -spzeros(Tv::Type, m::Integer, n::Integer) = spzeros(Tv, Int, m, n) -function spzeros(Tv::Type, Ti::Type, m::Integer, n::Integer) +spzeros(::Type{Tv}, m::Integer, n::Integer) where {Tv} = spzeros(Tv, Int, m, n) +function spzeros(::Type{Tv}, ::Type{Ti}, m::Integer, n::Integer) where {Tv, Ti} ((m < 0) || (n < 0)) && throw(ArgumentError("invalid Array dimensions")) SparseMatrixCSC(m, n, ones(Ti, n+1), Vector{Ti}(0), Vector{Tv}(0)) end # de-splatting variant -spzeros(Tv::Type, Ti::Type, sz::Tuple{Integer,Integer}) = spzeros(Tv, Ti, sz[1], sz[2]) +function spzeros(::Type{Tv}, ::Type{Ti}, sz::Tuple{Integer,Integer}) where {Tv, Ti} + spzeros(Tv, Ti, sz[1], sz[2]) +end speye(n::Integer) = speye(Float64, n) -speye(T::Type, n::Integer) = speye(T, n, n) +speye(::Type{T}, n::Integer) where {T} = speye(T, n, n) speye(m::Integer, n::Integer) = speye(Float64, m, n) """ @@ -1411,14 +1416,14 @@ eye(S::SparseMatrixCSC) = speye(S) speye([type,]m[,n]) Create a sparse identity matrix of size `m x m`. When `n` is supplied, -create a sparse identity matrix of size `m x n`. The type defaults to `Float64` +create a sparse identity matrix of size `m x n`. The type defaults to [`Float64`](@ref) if not specified. `sparse(I, m, n)` is equivalent to `speye(Int, m, n)`, and `sparse(α*I, m, n)` can be used to efficiently create a sparse multiple `α` of the identity matrix. """ -speye(T::Type, m::Integer, n::Integer) = speye_scaled(T, oneunit(T), m, n) +speye(::Type{T}, m::Integer, n::Integer) where {T} = speye_scaled(T, oneunit(T), m, n) function one(S::SparseMatrixCSC{T}) where T m,n = size(S) @@ -1428,7 +1433,7 @@ end speye_scaled(diag, m::Integer, n::Integer) = speye_scaled(typeof(diag), diag, m, n) -function speye_scaled(T, diag, m::Integer, n::Integer) +function speye_scaled(::Type{T}, diag, m::Integer, n::Integer) where T ((m < 0) || (n < 0)) && throw(ArgumentError("invalid array dimensions")) if iszero(diag) return SparseMatrixCSC(m, n, ones(Int, n+1), Vector{Int}(0), Vector{T}(0)) @@ -1447,6 +1452,10 @@ sparse(S::UniformScaling, m::Integer, n::Integer=m) = speye_scaled(S.λ, m, n) conj!(A::SparseMatrixCSC) = (@inbounds broadcast!(conj, A.nzval, A.nzval); A) (-)(A::SparseMatrixCSC) = SparseMatrixCSC(A.m, A.n, copy(A.colptr), copy(A.rowval), map(-, A.nzval)) +# the rest of real, conj, imag are handled correctly via AbstractArray methods +conj(A::SparseMatrixCSC{<:Complex}) = + SparseMatrixCSC(A.m, A.n, copy(A.colptr), copy(A.rowval), conj(A.nzval)) +imag(A::SparseMatrixCSC{Tv,Ti}) where {Tv<:Real,Ti} = spzeros(Tv, Ti, A.m, A.n) ## Binary arithmetic and boolean operators (+)(A::SparseMatrixCSC, B::SparseMatrixCSC) = map(+, A, B) @@ -1459,7 +1468,7 @@ conj!(A::SparseMatrixCSC) = (@inbounds broadcast!(conj, A.nzval, A.nzval); A) ## full equality function ==(A1::SparseMatrixCSC, A2::SparseMatrixCSC) - size(A1)!=size(A2) && return false + size(A1) != size(A2) && return false vals1, vals2 = nonzeros(A1), nonzeros(A2) rows1, rows2 = rowvals(A1), rowvals(A2) m, n = size(A1) @@ -1467,7 +1476,7 @@ function ==(A1::SparseMatrixCSC, A2::SparseMatrixCSC) nz1,nz2 = nzrange(A1,i), nzrange(A2,i) j1,j2 = first(nz1), first(nz2) # step through the rows of both matrices at once: - while j1<=last(nz1) && j2<=last(nz2) + while j1 <= last(nz1) && j2 <= last(nz2) r1,r2 = rows1[j1], rows2[j2] if r1==r2 vals1[j1]!=vals2[j2] && return false @@ -1499,13 +1508,13 @@ end # In general, output of sparse matrix reductions will not be sparse, # and computing reductions along columns into SparseMatrixCSC is # non-trivial, so use Arrays for output -Base.reducedim_initarray{R}(A::SparseMatrixCSC, region, v0, ::Type{R}) = +Base.reducedim_initarray(A::SparseMatrixCSC, region, v0, ::Type{R}) where {R} = fill!(similar(dims->Array{R}(dims), Base.reduced_indices(A,region)), v0) -Base.reducedim_initarray0{R}(A::SparseMatrixCSC, region, v0, ::Type{R}) = +Base.reducedim_initarray0(A::SparseMatrixCSC, region, v0, ::Type{R}) where {R} = fill!(similar(dims->Array{R}(dims), Base.reduced_indices0(A,region)), v0) # General mapreduce -function _mapreducezeros(f, op, T::Type, nzeros::Int, v0) +function _mapreducezeros(f, op, ::Type{T}, nzeros::Int, v0) where T nzeros == 0 && return v0 # Reduce over first zero @@ -1524,7 +1533,7 @@ function _mapreducezeros(f, op, T::Type, nzeros::Int, v0) v end -function Base._mapreduce{T}(f, op, ::Base.IndexCartesian, A::SparseMatrixCSC{T}) +function Base._mapreduce(f, op, ::Base.IndexCartesian, A::SparseMatrixCSC{T}) where T z = nnz(A) n = length(A) if z == 0 @@ -1539,12 +1548,12 @@ function Base._mapreduce{T}(f, op, ::Base.IndexCartesian, A::SparseMatrixCSC{T}) end # Specialized mapreduce for +/* -_mapreducezeros(f, ::typeof(+), T::Type, nzeros::Int, v0) = +_mapreducezeros(f, ::typeof(+), ::Type{T}, nzeros::Int, v0) where {T} = nzeros == 0 ? v0 : f(zero(T))*nzeros + v0 -_mapreducezeros(f, ::typeof(*), T::Type, nzeros::Int, v0) = +_mapreducezeros(f, ::typeof(*), ::Type{T}, nzeros::Int, v0) where {T} = nzeros == 0 ? v0 : f(zero(T))^nzeros * v0 -function Base._mapreduce{T}(f, op::typeof(*), A::SparseMatrixCSC{T}) +function Base._mapreduce(f, op::typeof(*), A::SparseMatrixCSC{T}) where T nzeros = length(A)-nnz(A) if nzeros == 0 # No zeros, so don't compute f(0) since it might throw @@ -1557,7 +1566,7 @@ function Base._mapreduce{T}(f, op::typeof(*), A::SparseMatrixCSC{T}) end # General mapreducedim -function _mapreducerows!{T}(f, op, R::AbstractArray, A::SparseMatrixCSC{T}) +function _mapreducerows!(f, op, R::AbstractArray, A::SparseMatrixCSC{T}) where T colptr = A.colptr rowval = A.rowval nzval = A.nzval @@ -1572,7 +1581,7 @@ function _mapreducerows!{T}(f, op, R::AbstractArray, A::SparseMatrixCSC{T}) R end -function _mapreducecols!{Tv,Ti}(f, op, R::AbstractArray, A::SparseMatrixCSC{Tv,Ti}) +function _mapreducecols!(f, op, R::AbstractArray, A::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} colptr = A.colptr rowval = A.rowval nzval = A.nzval @@ -1591,7 +1600,7 @@ function _mapreducecols!{Tv,Ti}(f, op, R::AbstractArray, A::SparseMatrixCSC{Tv,T R end -function Base._mapreducedim!{T}(f, op, R::AbstractArray, A::SparseMatrixCSC{T}) +function Base._mapreducedim!(f, op, R::AbstractArray, A::SparseMatrixCSC{T}) where T lsiz = Base.check_reducedims(R,A) isempty(A) && return R @@ -1641,7 +1650,7 @@ end # Specialized mapreducedim for + cols to avoid allocating a # temporary array when f(0) == 0 -function _mapreducecols!{Tv,Ti}(f, op::typeof(+), R::AbstractArray, A::SparseMatrixCSC{Tv,Ti}) +function _mapreducecols!(f, op::typeof(+), R::AbstractArray, A::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} nzval = A.nzval m, n = size(A) if length(nzval) == m*n @@ -1681,7 +1690,7 @@ function _mapreducecols!{Tv,Ti}(f, op::typeof(+), R::AbstractArray, A::SparseMat end # findmax/min and indmax/min methods -function _findz{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, rows=1:A.m, cols=1:A.n) +function _findz(A::SparseMatrixCSC{Tv,Ti}, rows=1:A.m, cols=1:A.n) where {Tv,Ti} colptr = A.colptr; rowval = A.rowval; nzval = A.nzval zval = zero(Tv) col = cols[1]; row = 0 @@ -1886,7 +1895,7 @@ function getindex(A::SparseMatrixCSC{Tv,Ti}, I::Range, J::AbstractVector) where return SparseMatrixCSC(nI, nJ, colptrS, rowvalS, nzvalS) end -function getindex_I_sorted{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) +function getindex_I_sorted(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) where {Tv,Ti} # Sorted vectors for indexing rows. # Similar to getindex_general but without the transpose trick. (m, n) = size(A) @@ -1906,7 +1915,7 @@ function getindex_I_sorted{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, getindex_I_sorted_linear(A, I, J) end -function getindex_I_sorted_bsearch_A{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) +function getindex_I_sorted_bsearch_A(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) where {Tv,Ti} const nI = length(I) const nJ = length(J) @@ -3249,7 +3258,7 @@ function next(d::SpDiagIterator{Tv}, j) where Tv (((r1 > r2) || (A.rowval[r1] != j)) ? zero(Tv) : A.nzval[r1], j+1) end -function trace{Tv}(A::SparseMatrixCSC{Tv}) +function trace(A::SparseMatrixCSC{Tv}) where Tv if size(A,1) != size(A,2) throw(DimensionMismatch("expected square matrix")) end @@ -3260,10 +3269,10 @@ function trace{Tv}(A::SparseMatrixCSC{Tv}) s end -diag{Tv}(A::SparseMatrixCSC{Tv}) = Tv[d for d in SpDiagIterator(A)] +diag(A::SparseMatrixCSC{Tv}) where {Tv} = Tv[d for d in SpDiagIterator(A)] -function diagm{Tv,Ti}(v::SparseMatrixCSC{Tv,Ti}) - if (size(v,1) != 1 && size(v,2) != 1) +function diagm(v::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} + if size(v,1) != 1 && size(v,2) != 1 throw(DimensionMismatch("input should be nx1 or 1xn")) end diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 7f915492a2fd31..d4f43de2296670 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -2,7 +2,7 @@ ### Common definitions -import Base: scalarmax, scalarmin, sort, find, findnz, @_pure_meta +import Base: scalarmax, scalarmin, sort, find, findnz import Base.LinAlg: promote_to_array_type, promote_to_arrays_ ### The SparseVector @@ -962,8 +962,8 @@ function hvcat(rows::Tuple{Vararg{Int}}, X::_SparseConcatGroup...) end # make sure UniformScaling objects are converted to sparse matrices for concatenation -promote_to_array_type(A::Tuple{Vararg{Union{_SparseConcatGroup,UniformScaling}}}) = (@_pure_meta; SparseMatrixCSC) -promote_to_array_type(A::Tuple{Vararg{Union{_DenseConcatGroup,UniformScaling}}}) = (@_pure_meta; Matrix) +promote_to_array_type(A::Tuple{Vararg{Union{_SparseConcatGroup,UniformScaling}}}) = SparseMatrixCSC +promote_to_array_type(A::Tuple{Vararg{Union{_DenseConcatGroup,UniformScaling}}}) = Matrix promote_to_arrays_(n::Int, ::Type{SparseMatrixCSC}, J::UniformScaling) = sparse(J, n, n) # Concatenations strictly involving un/annotated dense matrices/vectors should yield dense arrays @@ -985,7 +985,6 @@ hvcat(rows::Tuple{Vararg{Int}}, xs::_TypedDenseConcatGroup{T}...) where {T} = Ba ### Unary Map # zero-preserving functions (z->z, nz->nz) -conj(x::SparseVector) = SparseVector(length(x), copy(nonzeroinds(x)), conj(nonzeros(x))) -(x::SparseVector) = SparseVector(length(x), copy(nonzeroinds(x)), -(nonzeros(x))) # functions f, such that @@ -1019,9 +1018,9 @@ macro unarymap_nz2z_z2z(op, TF) end) end -real(x::AbstractSparseVector{<:Real}) = x +# the rest of real, conj, imag are handled correctly via AbstractArray methods @unarymap_nz2z_z2z real Complex - +conj(x::SparseVector{<:Complex}) = SparseVector(length(x), copy(nonzeroinds(x)), conj(nonzeros(x))) imag(x::AbstractSparseVector{Tv,Ti}) where {Tv<:Real,Ti<:Integer} = SparseVector(length(x), Ti[], Tv[]) @unarymap_nz2z_z2z imag Complex diff --git a/base/sparse/umfpack.jl b/base/sparse/umfpack.jl index 5e44206760f0fb..edb88f80304de3 100644 --- a/base/sparse/umfpack.jl +++ b/base/sparse/umfpack.jl @@ -107,8 +107,8 @@ end Compute the LU factorization of a sparse matrix `A`. For sparse `A` with real or complex element type, the return type of `F` is -`UmfpackLU{Tv, Ti}`, with `Tv` = `Float64` or `Complex128` respectively and -`Ti` is an integer type (`Int32` or `Int64`). +`UmfpackLU{Tv, Ti}`, with `Tv` = [`Float64`](@ref) or `Complex128` respectively and +`Ti` is an integer type ([`Int32`](@ref) or [`Int64`](@ref)). The individual components of the factorization `F` can be accessed by indexing: @@ -133,7 +133,7 @@ The relation between `F` and `A` is !!! note `lufact(A::SparseMatrixCSC)` uses the UMFPACK library that is part of - SuiteSparse. As this library only supports sparse matrices with `Float64` or + SuiteSparse. As this library only supports sparse matrices with [`Float64`](@ref) or `Complex128` elements, `lufact` converts `A` into a copy that is of type `SparseMatrixCSC{Float64}` or `SparseMatrixCSC{Complex128}` as appropriate. """ diff --git a/base/special/gamma.jl b/base/special/gamma.jl index 479ab58adfc0a2..7415200b409ce4 100644 --- a/base/special/gamma.jl +++ b/base/special/gamma.jl @@ -37,7 +37,7 @@ lfact(x::Integer) = x < 0 ? throw(DomainError()) : lgamma(x + oneunit(x)) lgamma(x) Compute the logarithm of the absolute value of [`gamma`](@ref) for -`Real` `x`, while for `Complex` `x` it computes the +[`Real`](@ref) `x`, while for [`Complex`](@ref) `x` compute the principal branch cut of the logarithm of `gamma(x)` (defined for negative `real(x)` by analytic continuation from positive `real(x)`). """ diff --git a/base/sysimg.jl b/base/sysimg.jl index 11a239a5f93bd0..31b1a6132009ea 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -162,7 +162,6 @@ include(string((length(Core.ARGS)>=2 ? Core.ARGS[2] : ""), "version_git.jl")) # include("osutils.jl") include("c.jl") -include("sysinfo.jl") if !isdefined(Core, :Inference) include("docs/core.jl") @@ -222,6 +221,7 @@ importall .Base64 include("version.jl") # system & environment +include("sysinfo.jl") include("libc.jl") using .Libc: getpid, gethostname, time include("libdl.jl") diff --git a/base/sysinfo.jl b/base/sysinfo.jl index d629db2f1c4ef8..95fc5ccb35f6ba 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -172,7 +172,7 @@ total_memory() = ccall(:uv_get_total_memory, UInt64, ()) Get the process title. On some systems, will always return an empty string. """ function get_process_title() - buf = zeros(UInt8, 512) + buf = Vector{UInt8}(512) err = ccall(:uv_get_process_title, Cint, (Ptr{UInt8}, Cint), buf, 512) Base.uv_error("get_process_title", err) return unsafe_string(pointer(buf)) @@ -193,19 +193,19 @@ maxrss() = ccall(:jl_maxrss, Csize_t, ()) if is_windows() function windows_version() verinfo = ccall(:GetVersion, UInt32, ()) - (Int(verinfo & 0xFF), Int((verinfo >> 8) & 0xFF)) + VersionNumber(verinfo & 0xFF, (verinfo >> 8) & 0xFF, verinfo >> 16) end else - windows_version() = (0, 0) + windows_version() = v"0.0" end """ Sys.windows_version() -Returns the version number for the Windows NT Kernel as a (major, minor) pair, -or `(0, 0)` if this is not running on Windows. +Returns the version number for the Windows NT Kernel as a `VersionNumber`, +i.e. `v"major.minor.build"`, or `v"0.0.0"` if this is not running on Windows. """ windows_version -const WINDOWS_VISTA_VER = (6, 0) +const WINDOWS_VISTA_VER = v"6.0" end # module Sys diff --git a/base/test.jl b/base/test.jl index a64c9679b0264a..9d7dc05bd553e3 100644 --- a/base/test.jl +++ b/base/test.jl @@ -115,7 +115,7 @@ end Error The test condition couldn't be evaluated due to an exception, or -it evaluated to something other than a `Bool`. +it evaluated to something other than a [`Bool`](@ref). In the case of `@test_broken` it is used to indicate that an unexpected `Pass` `Result` occurred. """ diff --git a/base/version.jl b/base/version.jl index 1bae427a645766..08938b3f48af9b 100644 --- a/base/version.jl +++ b/base/version.jl @@ -223,6 +223,8 @@ catch e VersionNumber(0) end +const libllvm_version = convert(VersionNumber, libllvm_version_string) + function banner(io::IO = STDOUT) if GIT_VERSION_INFO.tagged_commit commit_string = TAGGED_RELEASE_BANNER diff --git a/contrib/windows/get_toolchain.sh b/contrib/windows/get_toolchain.sh index 290a18195ef589..01e9ad973b2138 100755 --- a/contrib/windows/get_toolchain.sh +++ b/contrib/windows/get_toolchain.sh @@ -27,7 +27,7 @@ case $bits in ;; esac echo "Downloading $host toolchain, check $PWD/get_toolchain.log for full output" -contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win$bits/openSUSE_42.2 \ +contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win$bits/openSUSE_Leap_42.2 \ "mingw$bits-gcc mingw$bits-gcc-c++ mingw$bits-gcc-fortran \ mingw$bits-libssp0 mingw$bits-libstdc++6 mingw$bits-libgfortran3" > get_toolchain.log diff --git a/doc/REQUIRE b/doc/REQUIRE index e8869bde5e55a1..aed1a491d52250 100644 --- a/doc/REQUIRE +++ b/doc/REQUIRE @@ -1,3 +1,3 @@ Compat 0.25.0 0.25.0+ DocStringExtensions 0.3.3 0.3.3+ -Documenter 0.10.2 0.10.2+ +Documenter 0.10.3 0.10.3+ diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index 62006cf4d62d30..157dd60a624c0b 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -407,21 +407,21 @@ call. Finally, chains of comparisons have their own special expression structure ### Macros -| Input | AST | -|:------------- |:------------------------------------- | -| `@m x y` | `(macrocall @m x y)` | -| `Base.@m x y` | `(macrocall (. Base (quote @m)) x y)` | -| `@Base.m x y` | `(macrocall (. Base (quote @m)) x y)` | +| Input | AST | +|:------------- |:-------------------------------------------- | +| `@m x y` | `(macrocall @m (line) x y)` | +| `Base.@m x y` | `(macrocall (. Base (quote @m)) (line) x y)` | +| `@Base.m x y` | `(macrocall (. Base (quote @m)) (line) x y)` | ### Strings -| Input | AST | -|:--------------- |:---------------------------- | -| `"a"` | `"a"` | -| `x"y"` | `(macrocall @x_str "y")` | -| `x"y"z` | `(macrocall @x_str "y" "z")` | -| `"x = $x"` | `(string "x = " x)` | -| ``` `a b c` ``` | `(macrocall @cmd "a b c")` | +| Input | AST | +|:--------------- |:----------------------------------- | +| `"a"` | `"a"` | +| `x"y"` | `(macrocall @x_str (line) "y")` | +| `x"y"z` | `(macrocall @x_str (line) "y" "z")` | +| `"x = $x"` | `(string "x = " x)` | +| ``` `a b c` ``` | `(macrocall @cmd (line) "a b c")` | Doc string syntax: @@ -430,7 +430,7 @@ Doc string syntax: f(x) = x ``` -parses as `(macrocall (|.| Core '@doc) "some docs" (= (call f x) (block x)))`. +parses as `(macrocall (|.| Core '@doc) (line) "some docs" (= (call f x) (block x)))`. ### Imports and such @@ -449,11 +449,11 @@ parses as `(macrocall (|.| Core '@doc) "some docs" (= (call f x) (block x)))`. Julia supports more number types than many scheme implementations, so not all numbers are represented directly as scheme numbers in the AST. -| Input | AST | -|:----------------------- |:------------------------------------------------ | -| `11111111111111111111` | `(macrocall @int128_str "11111111111111111111")` | -| `0xfffffffffffffffff` | `(macrocall @uint128_str "0xfffffffffffffffff")` | -| `1111...many digits...` | `(macrocall @big_str "1111....")` | +| Input | AST | +|:----------------------- |:------------------------------------------------------- | +| `11111111111111111111` | `(macrocall @int128_str (null) "11111111111111111111")` | +| `0xfffffffffffffffff` | `(macrocall @uint128_str (null) "0xfffffffffffffffff")` | +| `1111...many digits...` | `(macrocall @big_str (null) "1111....")` | ### Block forms diff --git a/doc/src/devdocs/offset-arrays.md b/doc/src/devdocs/offset-arrays.md index 443473d16a61d5..689f856b48d623 100644 --- a/doc/src/devdocs/offset-arrays.md +++ b/doc/src/devdocs/offset-arrays.md @@ -59,7 +59,7 @@ the ranges may not start at 1. If you just want the range for a particular dime is `indices(A, d)`. Base implements a custom range type, `OneTo`, where `OneTo(n)` means the same thing as `1:n` but -in a form that guarantees (via the type system) that the lower index is 1. For any new `AbstractArray` +in a form that guarantees (via the type system) that the lower index is 1. For any new [`AbstractArray`](@ref) type, this is the default returned by `indices`, and it indicates that this array type uses "conventional" 1-based indexing. Note that if you don't want to be bothered supporting arrays with non-1 indexing, you can add the following line: @@ -108,8 +108,8 @@ Storage is often allocated with `Array{Int}(dims)` or `similar(A, args...)`. Whe to match the indices of some other array, this may not always suffice. The generic replacement for such patterns is to use `similar(storagetype, shape)`. `storagetype` indicates the kind of underlying "conventional" behavior you'd like, e.g., `Array{Int}` or `BitArray` or even `dims->zeros(Float32, dims)` -(which would allocate an all-zeros array). `shape` is a tuple of `Integer` or `AbstractUnitRange` -values, specifying the indices that you want the result to use. +(which would allocate an all-zeros array). `shape` is a tuple of [`Integer`](@ref) or +`AbstractUnitRange` values, specifying the indices that you want the result to use. Let's walk through a couple of explicit examples. First, if `A` has conventional indices, then `similar(Array{Int}, indices(A))` would end up calling `Array{Int}(size(A))`, and thus return diff --git a/doc/src/devdocs/reflection.md b/doc/src/devdocs/reflection.md index 9579a21eddaf6b..8baa61a222508e 100644 --- a/doc/src/devdocs/reflection.md +++ b/doc/src/devdocs/reflection.md @@ -50,7 +50,7 @@ of these fields is the `types` field observed in the example above. ## Subtypes The *direct* subtypes of any `DataType` may be listed using [`subtypes()`](@ref). For example, -the abstract `DataType``AbstractFloat` has four (concrete) subtypes: +the abstract `DataType` [`AbstractFloat`](@ref) has four (concrete) subtypes: ```jldoctest julia> subtypes(AbstractFloat) @@ -99,7 +99,8 @@ and variable assignments: julia> expand( :(f() = 1) ) :(begin $(Expr(:method, :f)) - $(Expr(:method, :f, :((Core.svec)((Core.svec)((Core.Typeof)(f)), (Core.svec)())), CodeInfo(:(begin # none, line 1: + $(Expr(:method, :f, :((Core.svec)((Core.svec)((Core.Typeof)(f)), (Core.svec)())), CodeInfo(:(begin + #= none:1 =# return 1 end)), false)) return f diff --git a/doc/src/devdocs/subarrays.md b/doc/src/devdocs/subarrays.md index 469907cd8fea1b..16a11c39cf7e3a 100644 --- a/doc/src/devdocs/subarrays.md +++ b/doc/src/devdocs/subarrays.md @@ -1,6 +1,6 @@ # SubArrays -Julia's `SubArray` type is a container encoding a "view" of a parent `AbstractArray`. This page +Julia's `SubArray` type is a container encoding a "view" of a parent [`AbstractArray`](@ref). This page documents some of the design principles and implementation of `SubArray`s. ## Indexing: cartesian vs. linear indexing diff --git a/doc/src/devdocs/types.md b/doc/src/devdocs/types.md index 63a274c61f74b5..5b3da02716a6ce 100644 --- a/doc/src/devdocs/types.md +++ b/doc/src/devdocs/types.md @@ -14,8 +14,8 @@ have. A *concrete* type `T` describes the set of values whose direct tag, as returned by the `typeof` function, is `T`. An *abstract* type describes some possibly-larger set of values. -`Any` describes the entire universe of possible values. `Integer` is a subset of `Any` that includes -`Int`, `Int8`, and other concrete types. +`Any` describes the entire universe of possible values. [`Integer`](@ref) is a subset of +`Any` that includes `Int`, [`Int8`](@ref), and other concrete types. Internally, Julia also makes heavy use of another type known as `Bottom`, which can also be written as `Union{}`. This corresponds to the empty set. @@ -330,7 +330,7 @@ However, this interpretation causes some practical problems. First, a value of `T` needs to be available inside the method definition. For a call like `f(1, 1.0)`, it's not clear what `T` should be. -It could be `Union{Int,Float64}`, or perhaps `Real`. +It could be `Union{Int,Float64}`, or perhaps [`Real`](@ref). Intuitively, we expect the declaration `x::T` to mean `T === typeof(x)`. To make sure that invariant holds, we need `typeof(x) === typeof(y) === T` in this method. That implies the method should only be called for arguments of the exact same type. @@ -433,7 +433,7 @@ When we are done evaluating the body of a `UnionAll` type whose variable is diag we look at the final values of the bounds. Since the variable must be concrete, a contradiction occurs if its lower bound could not be a subtype of a concrete type. -For example, an abstract type like `AbstractArray` cannot be a subtype of a concrete +For example, an abstract type like [`AbstractArray`](@ref) cannot be a subtype of a concrete type, but a concrete type like `Int` can be, and the empty type `Bottom` can be as well. If a lower bound fails this test the algorithm stops with the answer `false`. diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index e9d75f86440725..b99ae2cb050df7 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -10,7 +10,7 @@ on implementing a custom array type. An array is a collection of objects stored in a multi-dimensional grid. In the most general case, an array may contain objects of type `Any`. For most computational purposes, arrays should contain -objects of a more specific type, such as `Float64` or `Int32`. +objects of a more specific type, such as [`Float64`](@ref) or [`Int32`](@ref). In general, unlike many other technical computing languages, Julia does not expect programs to be written in a vectorized style for performance. Julia's compiler uses type inference and generates @@ -46,7 +46,7 @@ Many functions for constructing and initializing arrays are provided. In the fol such functions, calls with a `dims...` argument can either take a single tuple of dimension sizes or a series of dimension sizes passed as a variable number of arguments. Most of these functions also accept a first input `T`, which is the element type of the array. If the type `T` is -omitted it will default to `Float64`. +omitted it will default to [`Float64`](@ref). | Function | Description | |:---------------------------------- |:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -510,7 +510,7 @@ iterate over any array type. ### Array traits -If you write a custom `AbstractArray` type, you can specify that it has fast linear indexing using +If you write a custom [`AbstractArray`](@ref) type, you can specify that it has fast linear indexing using ```julia Base.IndexStyle(::Type{<:MyArray}) = IndexLinear() @@ -712,7 +712,7 @@ gains in either time or space when compared to performing the same operations on ### Compressed Sparse Column (CSC) Storage In Julia, sparse matrices are stored in the [Compressed Sparse Column (CSC) format](https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_column_.28CSC_or_CCS.29). -Julia sparse matrices have the type `SparseMatrixCSC{Tv,Ti}`, where `Tv` is the type of the nonzero +Julia sparse matrices have the type `SparseMatrixCSC{Tv,Ti}`, where `Tv` is the type of the stored values, and `Ti` is the integer type for storing column pointers and row indices.: ```julia @@ -720,8 +720,8 @@ struct SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrix{Tv,Ti} m::Int # Number of rows n::Int # Number of columns colptr::Vector{Ti} # Column i is in colptr[i]:(colptr[i+1]-1) - rowval::Vector{Ti} # Row values of nonzeros - nzval::Vector{Tv} # Nonzero values + rowval::Vector{Ti} # Row indices of stored values + nzval::Vector{Tv} # Stored values, typically nonzeros end ``` @@ -765,7 +765,7 @@ julia> speye(3,5) ``` The [`sparse()`](@ref) function is often a handy way to construct sparse matrices. It takes as -its input a vector `I` of row indices, a vector `J` of column indices, and a vector `V` of nonzero +its input a vector `I` of row indices, a vector `J` of column indices, and a vector `V` of stored values. `sparse(I,J,V)` constructs a sparse matrix such that `S[I[k], J[k]] = V[k]`. ```jldoctest sparse_function diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index b8164f86ad8da9..30da54ac330adb 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -66,7 +66,7 @@ julia> typeof(ans) Int32 ``` -`clock` takes no arguments and returns an `Int32`. One common gotcha is that a 1-tuple must be +`clock` takes no arguments and returns an [`Int32`](@ref). One common gotcha is that a 1-tuple must be written with a trailing comma. For example, to call the `getenv` function to get a pointer to the value of an environment variable, one makes a call like this: @@ -192,8 +192,8 @@ julia> const mycompare_c = cfunction(mycompare, Cint, (Ref{Cdouble}, Ref{Cdouble ``` [`cfunction()`](@ref) accepts three arguments: the Julia function (`mycompare`), the return type -(`Cint`), and a tuple of the argument types, in this case to sort an array of `Cdouble` (`Float64`) -elements. +(`Cint`), and a tuple of the argument types, in this case to sort an array of `Cdouble` +([`Float64`](@ref)) elements. The final call to `qsort` looks like this: @@ -298,7 +298,7 @@ same: * `Signed` Exactly corresponds to the `signed` type annotation in C (or any `INTEGER` type in Fortran). - Any Julia type that is not a subtype of `Signed` is assumed to be unsigned. + Any Julia type that is not a subtype of [`Signed`](@ref) is assumed to be unsigned. * `Ref{T}` diff --git a/doc/src/manual/complex-and-rational-numbers.md b/doc/src/manual/complex-and-rational-numbers.md index d3245c27a96393..29636b4a2f1398 100644 --- a/doc/src/manual/complex-and-rational-numbers.md +++ b/doc/src/manual/complex-and-rational-numbers.md @@ -143,7 +143,7 @@ julia> sqrt(-1) ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). Stacktrace: - [1] sqrt(::Int64) at ./math.jl:431 + [1] sqrt(::Int64) at ./math.jl:447 julia> sqrt(-1 + 0im) 0.0 + 1.0im @@ -283,8 +283,8 @@ Trying to construct a [`NaN`](@ref) rational value, however, is not: julia> 0//0 ERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64) Stacktrace: - [1] Rational{Int64}(::Int64, ::Int64) at ./rational.jl:8 - [2] //(::Int64, ::Int64) at ./rational.jl:35 + [1] Rational{Int64}(::Int64, ::Int64) at ./rational.jl:13 + [2] //(::Int64, ::Int64) at ./rational.jl:40 ``` As usual, the promotion system makes interactions with other numeric types effortless: diff --git a/doc/src/manual/constructors.md b/doc/src/manual/constructors.md index 607e7026712118..e9b46b392a4439 100644 --- a/doc/src/manual/constructors.md +++ b/doc/src/manual/constructors.md @@ -313,10 +313,10 @@ Point{Float64}(1.0, 2.0) As you can see, for constructor calls with explicit type parameters, the arguments are converted to the implied field types: `Point{Int64}(1,2)` works, but `Point{Int64}(1.0,2.5)` raises an -[`InexactError`](@ref) when converting `2.5` to `Int64`. When the type is implied by the arguments to -the constructor call, as in `Point(1,2)`, then the types of the arguments must agree -- otherwise -the `T` cannot be determined -- but any pair of real arguments with matching type may be given -to the generic `Point` constructor. +[`InexactError`](@ref) when converting `2.5` to [`Int64`](@ref). When the type is implied +by the arguments to the constructor call, as in `Point(1,2)`, then the types of the +arguments must agree -- otherwise the `T` cannot be determined -- but any pair of real +arguments with matching type may be given to the generic `Point` constructor. What's really going on here is that `Point`, `Point{Float64}` and `Point{Int64}` are all different constructor functions. In fact, `Point{T}` is a distinct constructor function for each type `T`. @@ -551,10 +551,11 @@ SummedArray{Int32,Int32}(Int32[1, 2, 3], 6) ``` The problem is that we want `S` to be a larger type than `T`, so that we can sum many elements -with less information loss. For example, when `T` is `Int32`, we would like `S` to be `Int64`. -Therefore we want to avoid an interface that allows the user to construct instances of the type -`SummedArray{Int32,Int32}`. One way to do this is to provide a constructor only for `SummedArray`, -but inside the `type` definition block to suppress generation of default constructors: +with less information loss. For example, when `T` is [`Int32`](@ref), we would like `S` to +be [`Int64`](@ref). Therefore we want to avoid an interface that allows the user to construct +instances of the type `SummedArray{Int32,Int32}`. One way to do this is to provide a +constructor only for `SummedArray`, but inside the `type` definition block to suppress +generation of default constructors: ```jldoctest julia> struct SummedArray{T<:Number,S<:Number} diff --git a/doc/src/manual/control-flow.md b/doc/src/manual/control-flow.md index 1bf0923b6cb402..e06586239edd1e 100644 --- a/doc/src/manual/control-flow.md +++ b/doc/src/manual/control-flow.md @@ -173,8 +173,8 @@ julia> if 1 ERROR: TypeError: non-boolean (Int64) used in boolean context ``` -This error indicates that the conditional was of the wrong type: `Int64` rather than the required -`Bool`. +This error indicates that the conditional was of the wrong type: [`Int64`](@ref) rather +than the required [`Bool`](@ref). The so-called "ternary operator", `?:`, is closely related to the `if`-`elseif`-`else` syntax, but is used where a conditional choice between single expression values is required, as opposed @@ -571,7 +571,7 @@ julia> sqrt(-1) ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). Stacktrace: - [1] sqrt(::Int64) at ./math.jl:431 + [1] sqrt(::Int64) at ./math.jl:447 ``` You may define your own exceptions in the following way: diff --git a/doc/src/manual/conversion-and-promotion.md b/doc/src/manual/conversion-and-promotion.md index b72d2715b6aeb7..5cc15a893ef4ed 100644 --- a/doc/src/manual/conversion-and-promotion.md +++ b/doc/src/manual/conversion-and-promotion.md @@ -101,13 +101,14 @@ is to it. For example, the method to convert a real number to a boolean is this: convert(::Type{Bool}, x::Real) = x==0 ? false : x==1 ? true : throw(InexactError()) ``` -The type of the first argument of this method is a [singleton type](@ref man-singleton-types), `Type{Bool}`, the only -instance of which is `Bool`. Thus, this method is only invoked when the first argument is the -type value `Bool`. Notice the syntax used for the first argument: the argument name is omitted -prior to the `::` symbol, and only the type is given. This is the syntax in Julia for a function -argument whose type is specified but whose value is never used in the function body. In this -example, since the type is a singleton, there would never be any reason to use its value within -the body. When invoked, the method determines whether a numeric value is true or false as a boolean, +The type of the first argument of this method is a [singleton type](@ref man-singleton-types), +`Type{Bool}`, the only instance of which is [`Bool`](@ref). Thus, this method is only invoked +when the first argument is the type value `Bool`. Notice the syntax used for the first +argument: the argument name is omitted prior to the `::` symbol, and only the type is given. +This is the syntax in Julia for a function argument whose type is specified but whose value +is never used in the function body. In this example, since the type is a singleton, there +would never be any reason to use its value within the body. When invoked, the method +determines whether a numeric value is true or false as a boolean, by comparing it to one and zero: ```jldoctest @@ -120,7 +121,7 @@ false julia> convert(Bool, 1im) ERROR: InexactError() Stacktrace: - [1] convert(::Type{Bool}, ::Complex{Int64}) at ./complex.jl:23 + [1] convert(::Type{Bool}, ::Complex{Int64}) at ./complex.jl:31 julia> convert(Bool, 0im) false @@ -137,7 +138,8 @@ convert(::Type{T}, z::Complex) where {T<:Real} = ### [Case Study: Rational Conversions](@id man-rational-conversion) -To continue our case study of Julia's `Rational` type, here are the conversions declared in [`rational.jl`](https://github.com/JuliaLang/julia/blob/master/base/rational.jl), +To continue our case study of Julia's [`Rational`](@ref) type, here are the conversions declared in +[`rational.jl`](https://github.com/JuliaLang/julia/blob/master/base/rational.jl), right after the declaration of the type and its constructors: ```julia @@ -187,8 +189,8 @@ since the values are converted to a "greater" type -- i.e. one which can represe input values in a single common type. It is important, however, not to confuse this with object-oriented (structural) super-typing, or Julia's notion of abstract super-types: promotion has nothing to do with the type hierarchy, and everything to do with converting between alternate representations. -For instance, although every `Int32` value can also be represented as a `Float64` value, `Int32` -is not a subtype of `Float64`. +For instance, although every [`Int32`](@ref) value can also be represented as a [`Float64`](@ref) value, +`Int32` is not a subtype of `Float64`. Promotion to a common "greater" type is performed in Julia by the `promote` function, which takes any number of arguments, and returns a tuple of the same number of values, converted to a common @@ -286,10 +288,11 @@ promote_rule(::Type{UInt8}, ::Type{Int8}) = Int promote_rule(::Type{BigInt}, ::Type{Int8}) = BigInt ``` -In the latter case, the result type is `BigInt` since `BigInt` is the only type large enough to -hold integers for arbitrary-precision integer arithmetic. Also note that one does not need to -define both `promote_rule(::Type{A}, ::Type{B})` and `promote_rule(::Type{B}, ::Type{A})` -- the -symmetry is implied by the way `promote_rule` is used in the promotion process. +In the latter case, the result type is [`BigInt`](@ref) since `BigInt` is the only type +large enough to hold integers for arbitrary-precision integer arithmetic. Also note that +one does not need to define both `promote_rule(::Type{A}, ::Type{B})` and +`promote_rule(::Type{B}, ::Type{A})` -- the symmetry is implied by the way `promote_rule` +is used in the promotion process. The `promote_rule` function is used as a building block to define a second function called `promote_type`, which, given any number of type objects, returns the common type to which those values, as arguments diff --git a/doc/src/manual/dates.md b/doc/src/manual/dates.md index 70645cacd1d931..476314407e6ab3 100644 --- a/doc/src/manual/dates.md +++ b/doc/src/manual/dates.md @@ -12,10 +12,10 @@ For example, since the [`Date`](@ref) type only resolves to the precision of a s no hours, minutes, or seconds), normal considerations for time zones, daylight savings/summer time, and leap seconds are unnecessary and avoided. -Both [`Date`](@ref) and [`DateTime`](@ref) are basically immutable `Int64` wrappers. The single -`instant` field of either type is actually a `UTInstant{P}` type, which represents a continuously -increasing machine timeline based on the UT second [^1]. The [`DateTime`](@ref) -type is not aware of time zones (*naive*, in Python parlance), +Both [`Date`](@ref) and [`DateTime`](@ref) are basically immutable [`Int64`](@ref) wrappers. +The single `instant` field of either type is actually a `UTInstant{P}` type, which +represents a continuously increasing machine timeline based on the UT second [^1]. The +[`DateTime`](@ref) type is not aware of time zones (*naive*, in Python parlance), analogous to a *LocalDateTime* in Java 8. Additional time zone functionality can be added through the [TimeZones.jl package](https://github.com/JuliaTime/TimeZones.jl/), which compiles the [IANA time zone database](http://www.iana.org/time-zones). Both [`Date`](@ref) and @@ -133,7 +133,7 @@ Finding the length of time between two [`Date`](@ref) or [`DateTime`](@ref) is s given their underlying representation as `UTInstant{Day}` and `UTInstant{Millisecond}`, respectively. The difference between [`Date`](@ref) is returned in the number of [`Day`](@ref), and [`DateTime`](@ref) in the number of [`Millisecond`](@ref). Similarly, comparing [`TimeType`](@ref) is a simple matter -of comparing the underlying machine instants (which in turn compares the internal `Int64` values). +of comparing the underlying machine instants (which in turn compares the internal [`Int64`](@ref) values). ```jldoctest julia> dt = Date(2012,2,29) @@ -190,7 +190,7 @@ julia> dt - dt2 ## Accessor Functions -Because the [`Date`](@ref) and [`DateTime`](@ref) types are stored as single `Int64` values, date +Because the [`Date`](@ref) and [`DateTime`](@ref) types are stored as single [`Int64`](@ref) values, date parts or fields can be retrieved through accessor functions. The lowercase accessors return the field as an integer: @@ -454,7 +454,8 @@ julia> Dates.lastdayofquarter(Date(2014,7,16)) # Adjusts to the last day of the The next two higher-order methods, [`tonext()`](@ref), and [`toprev()`](@ref), generalize working with temporal expressions by taking a `DateFunction` as first argument, along with a starting [`TimeType`](@ref). A `DateFunction` is just a function, usually anonymous, that takes a single -[`TimeType`](@ref) as input and returns a `Bool`, `true` indicating a satisfied adjustment criterion. +[`TimeType`](@ref) as input and returns a [`Bool`](@ref), `true` indicating a satisfied +adjustment criterion. For example: ```jldoctest @@ -511,7 +512,7 @@ Additional examples and tests are available in [`test/dates/adjusters.jl`](https Periods are a human view of discrete, sometimes irregular durations of time. Consider 1 month; it could represent, in days, a value of 28, 29, 30, or 31 depending on the year and month context. Or a year could represent 365 or 366 days in the case of a leap year. [`Period`](@ref) types are -simple `Int64` wrappers and are constructed by wrapping any `Int64` convertible type, i.e. `Year(1)` +simple [`Int64`](@ref) wrappers and are constructed by wrapping any `Int64` convertible type, i.e. `Year(1)` or `Month(3.0)`. Arithmetic between [`Period`](@ref) of the same type behave like integers, and limited `Period-Real` arithmetic is available. diff --git a/doc/src/manual/documentation.md b/doc/src/manual/documentation.md index 59d1a23f2e43d5..284fe75c499112 100644 --- a/doc/src/manual/documentation.md +++ b/doc/src/manual/documentation.md @@ -109,8 +109,8 @@ As in the example above, we recommend following some simple conventions when wri Calling `rand` and other RNG-related functions should be avoided in doctests since they will not produce consistent outputs during different Julia sessions. - Operating system word size (`Int32` or `Int64`) as well as path separator differences (`/` or - `\`) will also effect the reproducibility of some doctests. + Operating system word size ([`Int32`](@ref) or [`Int64`](@ref)) as well as path separator differences + (`/` or `\`) will also affect the reproducibility of some doctests. Note that whitespace in your doctest is significant! The doctest will fail if you misalign the output of pretty-printing an array, for example. diff --git a/doc/src/manual/embedding.md b/doc/src/manual/embedding.md index 77a132c5b3d205..032b57dcedc439 100644 --- a/doc/src/manual/embedding.md +++ b/doc/src/manual/embedding.md @@ -139,9 +139,9 @@ Now the build command is simply `make`. Real applications will not just need to execute expressions, but also return their values to the host program. `jl_eval_string` returns a `jl_value_t*`, which is a pointer to a heap-allocated -Julia object. Storing simple data types like `Float64` in this way is called `boxing`, and extracting -the stored primitive data is called `unboxing`. Our improved sample program that calculates the -square root of 2 in Julia and reads back the result in C looks as follows: +Julia object. Storing simple data types like [`Float64`](@ref) in this way is called `boxing`, +and extracting the stored primitive data is called `unboxing`. Our improved sample program that +calculates the square root of 2 in Julia and reads back the result in C looks as follows: ```c jl_value_t *ret = jl_eval_string("sqrt(2.0)"); @@ -157,9 +157,9 @@ else { In order to check whether `ret` is of a specific Julia type, we can use the `jl_isa`, `jl_typeis`, or `jl_is_...` functions. -By typing `typeof(sqrt(2.0))` into the Julia shell we can see that the return type is `Float64` -(`double` in C). To convert the boxed Julia value into a C double the `jl_unbox_float64` function -is used in the above code snippet. +By typing `typeof(sqrt(2.0))` into the Julia shell we can see that the return type is +[`Float64`](@ref) (`double` in C). To convert the boxed Julia value into a C double the +`jl_unbox_float64` function is used in the above code snippet. Corresponding `jl_box_...` functions are used to convert the other way: diff --git a/doc/src/manual/environment-variables.md b/doc/src/manual/environment-variables.md index bbb2c41e27a91b..d2fe606136b762 100644 --- a/doc/src/manual/environment-variables.md +++ b/doc/src/manual/environment-variables.md @@ -175,7 +175,7 @@ logical CPU cores available. ### `JULIA_WORKER_TIMEOUT` -A `Float64` that sets the value of `Base.worker_timeout()` (default: `60.0`). +A [`Float64`](@ref) that sets the value of `Base.worker_timeout()` (default: `60.0`). This function gives the number of seconds a worker process will wait for a master process to establish a connection before dying. diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index e019cce47fa78a..39a03f30c13fd5 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -214,9 +214,10 @@ julia> function unstable(flag::Bool) unstable (generic function with 1 method) ``` -It returns either an `Int` or a `Float64` depending on the value of its argument. Since Julia -can't predict the return type of this function at compile-time, any computation that uses it will -have to guard against both types possibly occurring, making generation of fast machine code difficult. +It returns either an `Int` or a [`Float64`](@ref) depending on the value of its argument. +Since Julia can't predict the return type of this function at compile-time, any computation +that uses it will have to guard against both types possibly occurring, making generation of +fast machine code difficult. ### [Why does Julia give a `DomainError` for certain seemingly-sensible operations?](@id faq-domain-errors) @@ -227,7 +228,7 @@ julia> sqrt(-2.0) ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). Stacktrace: - [1] sqrt(::Float64) at ./math.jl:422 + [1] sqrt(::Float64) at ./math.jl:438 julia> 2^-5 ERROR: DomainError: @@ -281,7 +282,7 @@ ideal for a high-level programming language to expose this to the user. For nume efficiency and transparency are at a premium, however, the alternatives are worse. One alternative to consider would be to check each integer operation for overflow and promote -results to bigger integer types such as `Int128` or [`BigInt`](@ref) in the case of overflow. +results to bigger integer types such as [`Int128`](@ref) or [`BigInt`](@ref) in the case of overflow. Unfortunately, this introduces major overhead on every integer operation (think incrementing a loop counter) – it requires emitting code to perform run-time overflow checks after arithmetic instructions and branches to handle potential overflows. Worse still, this would cause every computation diff --git a/doc/src/manual/integers-and-floating-point-numbers.md b/doc/src/manual/integers-and-floating-point-numbers.md index 5e1c54347bd3f8..1b819938cc625e 100644 --- a/doc/src/manual/integers-and-floating-point-numbers.md +++ b/doc/src/manual/integers-and-floating-point-numbers.md @@ -18,25 +18,25 @@ The following are Julia's primitive numeric types: * **Integer types:** -| Type | Signed? | Number of bits | Smallest value | Largest value | -|:--------- |:------- |:-------------- |:-------------- |:------------- | -| `Int8` | ✓ | 8 | -2^7 | 2^7 - 1 | -| `UInt8` |   | 8 | 0 | 2^8 - 1 | -| `Int16` | ✓ | 16 | -2^15 | 2^15 - 1 | -| `UInt16` |   | 16 | 0 | 2^16 - 1 | -| `Int32` | ✓ | 32 | -2^31 | 2^31 - 1 | -| `UInt32` |   | 32 | 0 | 2^32 - 1 | -| `Int64` | ✓ | 64 | -2^63 | 2^63 - 1 | -| `UInt64` |   | 64 | 0 | 2^64 - 1 | -| `Int128` | ✓ | 128 | -2^127 | 2^127 - 1 | -| `UInt128` |   | 128 | 0 | 2^128 - 1 | -| `Bool` | N/A | 8 | `false` (0) | `true` (1) | +| Type | Signed? | Number of bits | Smallest value | Largest value | +|:----------------- |:------- |:-------------- |:-------------- |:------------- | +| [`Int8`](@ref) | ✓ | 8 | -2^7 | 2^7 - 1 | +| [`UInt8`](@ref) |   | 8 | 0 | 2^8 - 1 | +| [`Int16`](@ref) | ✓ | 16 | -2^15 | 2^15 - 1 | +| [`UInt16`](@ref) |   | 16 | 0 | 2^16 - 1 | +| [`Int32`](@ref) | ✓ | 32 | -2^31 | 2^31 - 1 | +| [`UInt32`](@ref) |   | 32 | 0 | 2^32 - 1 | +| [`Int64`](@ref) | ✓ | 64 | -2^63 | 2^63 - 1 | +| [`UInt64`](@ref) |   | 64 | 0 | 2^64 - 1 | +| [`Int128`](@ref) | ✓ | 128 | -2^127 | 2^127 - 1 | +| [`UInt128`](@ref) |   | 128 | 0 | 2^128 - 1 | +| [`Bool`](@ref) | N/A | 8 | `false` (0) | `true` (1) | * **Floating-point types:** | Type | Precision | Number of bits | |:----------------- |:------------------------------------------------------------------------------ |:-------------- | -| `Float16` | [half](https://en.wikipedia.org/wiki/Half-precision_floating-point_format) | 16 | +| [`Float16`](@ref) | [half](https://en.wikipedia.org/wiki/Half-precision_floating-point_format) | 16 | | [`Float32`](@ref) | [single](https://en.wikipedia.org/wiki/Single_precision_floating-point_format) | 32 | | [`Float64`](@ref) | [double](https://en.wikipedia.org/wiki/Double_precision_floating-point_format) | 64 | @@ -206,7 +206,7 @@ true Thus, arithmetic with Julia integers is actually a form of [modular arithmetic](https://en.wikipedia.org/wiki/Modular_arithmetic). This reflects the characteristics of the underlying arithmetic of integers as implemented on modern computers. In applications where overflow is possible, explicit checking for wraparound produced -by overflow is essential; otherwise, the `BigInt` type in [Arbitrary Precision Arithmetic](@ref) +by overflow is essential; otherwise, the [`BigInt`](@ref) type in [Arbitrary Precision Arithmetic](@ref) is recommended instead. ### Division errors @@ -243,8 +243,8 @@ julia> 2.5e-4 0.00025 ``` -The above results are all `Float64` values. Literal `Float32` values can be entered by writing -an `f` in place of `e`: +The above results are all [`Float64`](@ref) values. Literal [`Float32`](@ref) values can be +entered by writing an `f` in place of `e`: ```jldoctest julia> 0.5f0 @@ -257,7 +257,7 @@ julia> 2.5f-4 0.00025f0 ``` -Values can be converted to `Float32` easily: +Values can be converted to [`Float32`](@ref) easily: ```jldoctest julia> Float32(-1.5) @@ -267,7 +267,7 @@ julia> typeof(ans) Float32 ``` -Hexadecimal floating-point literals are also valid, but only as `Float64` values: +Hexadecimal floating-point literals are also valid, but only as [`Float64`](@ref) values: ```jldoctest julia> 0x1p0 @@ -283,8 +283,8 @@ julia> typeof(ans) Float64 ``` -Half-precision floating-point numbers are also supported (`Float16`), but they are -implemented in software and use `Float32` for calculations. +Half-precision floating-point numbers are also supported ([`Float16`](@ref)), but they are +implemented in software and use [`Float32`](@ref) for calculations. ```jldoctest julia> sizeof(Float16(4.)) @@ -404,11 +404,11 @@ julia> eps() # same as eps(Float64) 2.220446049250313e-16 ``` -These values are `2.0^-23` and `2.0^-52` as `Float32` and `Float64` values, respectively. The -[`eps()`](@ref) function can also take a floating-point value as an argument, and gives the absolute -difference between that value and the next representable floating point value. That is, `eps(x)` -yields a value of the same type as `x` such that `x + eps(x)` is the next representable floating-point -value larger than `x`: +These values are `2.0^-23` and `2.0^-52` as [`Float32`](@ref) and [`Float64`](@ref) values, +respectively. The [`eps()`](@ref) function can also take a floating-point value as an +argument, and gives the absolute difference between that value and the next representable +floating point value. That is, `eps(x)` yields a value of the same type as `x` such that +`x + eps(x)` is the next representable floating-point value larger than `x`: ```jldoctest julia> eps(1.0) diff --git a/doc/src/manual/interfaces.md b/doc/src/manual/interfaces.md index fd7b5cba85501e..91ae4fbe21e570 100644 --- a/doc/src/manual/interfaces.md +++ b/doc/src/manual/interfaces.md @@ -187,7 +187,7 @@ julia> Squares(10)[[3,4.,5]] While this is starting to support more of the [indexing operations supported by some of the builtin types](@ref man-array-indexing), there's still quite a number of behaviors missing. This `Squares` sequence is starting to look more and more like a vector as we've added behaviors to it. Instead of defining all these behaviors -ourselves, we can officially define it as a subtype of an `AbstractArray`. +ourselves, we can officially define it as a subtype of an [`AbstractArray`](@ref). ## [Abstract Arrays](@id man-interface-array) diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index 2727ec20cd8539..a6ff8bdea53f8b 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -21,7 +21,7 @@ are supported on all primitive numeric types: | `x ^ y` | power | raises `x` to the `y`th power | | `x % y` | remainder | equivalent to `rem(x,y)` | -as well as the negation on `Bool` types: +as well as the negation on [`Bool`](@ref) types: | Expression | Name | Description | |:---------- |:-------- |:---------------------------------------- | diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index 2351621e6269e1..a6d3fa57840e59 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -194,9 +194,12 @@ julia> ex = quote y = 2 x + y end -quote # none, line 2: - x = 1 # none, line 3: - y = 2 # none, line 4: +quote + #= none:2 =# + x = 1 + #= none:3 =# + y = 2 + #= none:4 =# x + y end @@ -509,6 +512,28 @@ julia> @showarg(println("Yo!")) :(println("Yo!")) ``` +In addition to the given argument list, every macro is passed an extra argument named `__source__` +providing information (in the form of a `LineNumberNode` object) about the parser location +of the `@` sign from the macro invocation. + +This allows macros to include better error diagnostic information, +and is commonly used by logging, string-parser macros, and docs, for example, +as well as to implement the `@__LINE__`, `@__FILE__`, and `@__DIR__` macros. + +The location information can be accessed by referencing `__source__.line` and `__source__.file`: + +```jldoctest +julia> macro __LOCATION__(); return QuoteNode(__source__); end +@__LOCATION__ (macro with 1 method) + +julia> dump( + @__LOCATION__( + )) +LineNumberNode + line: Int64 2 + file: Symbol none +``` + ### Building an advanced macro Here is a simplified definition of Julia's `@assert` macro: @@ -708,6 +733,32 @@ julia> foo() This kind of manipulation of variables should be used judiciously, but is occasionally quite handy. +Getting the hygiene rules correct can be a formidable challenge. +Before using a macro, you might want to consider whether a function closure +would be sufficient. Another useful strategy is to defer as much work as possible to runtime. +For example, many macros simply wrap their arguments in a QuoteNode or other similar Expr. +Some examples of this include `@task body` which simply returns `schedule(Task(() -> $body))`, +and `@eval expr`, which simply returns `eval(QuoteNode(expr))`. + +To demonstrate, we might rewrite the `@time` example above as: + +```julia +macro time(expr) + return :(timeit(() -> $(esc(expr)))) +end +function timeit(f) + t0 = time() + val = f() + t1 = time() + println("elapsed time: ", t1-t0, " seconds") + return val +end +``` + +However, we don't do this for a good reason: wrapping the `expr` in a new scope block (the anonymous function) +also slightly changes the meaning of the expression (the scope of any variables in it), +while we want `@time` to be usable with minimum impact on the wrapped code. + ## Code Generation When a significant amount of repetitive boilerplate code is required, it is common to generate @@ -925,7 +976,7 @@ julia> foo(4) 16 ``` -Note that there is no printout of `Int64`. We can see that the body of the generated function +Note that there is no printout of [`Int64`](@ref). We can see that the body of the generated function was only executed once here, for the specific set of argument types, and the result was cached. After that, for this example, the expression returned from the generated function on the first invocation was re-used as the method body. However, the actual caching behavior is an implementation-defined diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index bc649bf4c2f35d..c8843e18b0635e 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -58,7 +58,8 @@ julia> f(x::Float64, y::Float64) = 2x + y f (generic function with 1 method) ``` -This function definition applies only to calls where `x` and `y` are both values of type `Float64`: +This function definition applies only to calls where `x` and `y` are both values of type +[`Float64`](@ref): ```jldoctest fofxy julia> f(2.0, 3.0) @@ -87,12 +88,12 @@ julia> f("2.0", "3.0") ERROR: MethodError: no method matching f(::String, ::String) ``` -As you can see, the arguments must be precisely of type `Float64`. Other numeric types, such as -integers or 32-bit floating-point values, are not automatically converted to 64-bit floating-point, -nor are strings parsed as numbers. Because `Float64` is a concrete type and concrete types cannot -be subclassed in Julia, such a definition can only be applied to arguments that are exactly of -type `Float64`. It may often be useful, however, to write more general methods where the declared -parameter types are abstract: +As you can see, the arguments must be precisely of type [`Float64`](@ref). Other numeric +types, such as integers or 32-bit floating-point values, are not automatically converted +to 64-bit floating-point, nor are strings parsed as numbers. Because `Float64` is a concrete +type and concrete types cannot be subclassed in Julia, such a definition can only be applied +to arguments that are exactly of type `Float64`. It may often be useful, however, to write +more general methods where the declared parameter types are abstract: ```jldoctest fofxy julia> f(x::Number, y::Number) = 2x - y @@ -102,9 +103,10 @@ julia> f(2.0, 3) 1.0 ``` -This method definition applies to any pair of arguments that are instances of `Number`. They need -not be of the same type, so long as they are each numeric values. The problem of handling disparate -numeric types is delegated to the arithmetic operations in the expression `2x - y`. +This method definition applies to any pair of arguments that are instances of [`Number`](@ref). +They need not be of the same type, so long as they are each numeric values. The problem of +handling disparate numeric types is delegated to the arithmetic operations in the +expression `2x - y`. To define a function with multiple methods, one simply defines the function multiple times, with different numbers and types of arguments. The first method definition for a function creates the @@ -112,9 +114,9 @@ function object, and subsequent method definitions add new methods to the existi The most specific method definition matching the number and types of the arguments will be executed when the function is applied. Thus, the two method definitions above, taken together, define the behavior for `f` over all pairs of instances of the abstract type `Number` -- but with a different -behavior specific to pairs of `Float64` values. If one of the arguments is a 64-bit float but -the other one is not, then the `f(Float64,Float64)` method cannot be called and the more general -`f(Number,Number)` method must be used: +behavior specific to pairs of [`Float64`](@ref) values. If one of the arguments is a 64-bit +float but the other one is not, then the `f(Float64,Float64)` method cannot be called and +the more general `f(Number,Number)` method must be used: ```jldoctest fofxy julia> f(2.0, 3.0) diff --git a/doc/src/manual/noteworthy-differences.md b/doc/src/manual/noteworthy-differences.md index 5457f201dbd6d1..98740263fc3640 100644 --- a/doc/src/manual/noteworthy-differences.md +++ b/doc/src/manual/noteworthy-differences.md @@ -239,11 +239,11 @@ For users coming to Julia from R, these are some noteworthy differences: unsigned and/or signed vs. unsigned. Decimal literals are always signed, and hexadecimal literals (which start with `0x` like C/C++), are unsigned. Hexadecimal literals also, unlike C/C++/Java and unlike decimal literals in Julia, have a type based on the *length* of the literal, including - leading 0s. For example, `0x0` and `0x00` have type UInt8, `0x000` and `0x0000` have type `UInt16`, - then literals with 5 to 8 hex digits have type `UInt32`, 9 to 16 hex digits type `UInt64` and - 17 to 32 hex digits type `UInt128`. This needs to be taken into account when defining hexadecimal - masks, for example `~0xf == 0xf0` is very different from `~0x000f == 0xfff0`. 64 bit `Float64` - and 32 bit `Float32` bit literals are expressed as `1.0` and `1.0f0` respectively. Floating point + leading 0s. For example, `0x0` and `0x00` have type [`UInt8`](@ref), `0x000` and `0x0000` have type + [`UInt16`](@ref), then literals with 5 to 8 hex digits have type `UInt32`, 9 to 16 hex digits type + `UInt64` and 17 to 32 hex digits type `UInt128`. This needs to be taken into account when defining + hexadecimal masks, for example `~0xf == 0xf0` is very different from `~0x000f == 0xfff0`. 64 bit `Float64` + and 32 bit [`Float32`](@ref) bit literals are expressed as `1.0` and `1.0f0` respectively. Floating point literals are rounded (and not promoted to the `BigFloat` type) if they can not be exactly represented. Floating point literals are closer in behavior to C/C++. Octal (prefixed with `0o`) and binary (prefixed with `0b`) literals are also treated as unsigned. @@ -251,7 +251,7 @@ For users coming to Julia from R, these are some noteworthy differences: `"` characters without quoting it like `"\""` String literals can have values of other variables or expressions interpolated into them, indicated by `$variablename` or `$(expression)`, which evaluates the variable name or the expression in the context of the function. - * `//` indicates a `Rational` number, and not a single-line comment (which is `#` in Julia) + * `//` indicates a [`Rational`](@ref) number, and not a single-line comment (which is `#` in Julia) * `#=` indicates the start of a multiline comment, and `=#` ends it. * Functions in Julia return values from their last expression(s) or the `return` keyword. Multiple values can be returned from functions and assigned as tuples, e.g. `(a, b) = myfunction()` or diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index 14c91c0d9e3794..92fd3bc55aa30c 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -137,10 +137,10 @@ if (f = rand()) < .8 end ``` -Because `a` is a an array of abstract type `Real`, it must be able to hold any `Real` value. Since -`Real` objects can be of arbitrary size and structure, `a` must be represented as an array of -pointers to individually allocated `Real` objects. Because `f` will always be a [`Float64`](@ref), -we should instead, use: +Because `a` is a an array of abstract type [`Real`](@ref), it must be able to hold any +`Real` value. Since `Real` objects can be of arbitrary size and structure, `a` must be +represented as an array of pointers to individually allocated `Real` objects. Because `f` +will always be a [`Float64`](@ref), we should instead, use: ```julia a = Float64[] # typeof(a) = Array{Float64,1} @@ -188,9 +188,9 @@ MyAmbiguousType `b` and `c` have the same type, yet their underlying representation of data in memory is very different. Even if you stored just numeric values in field `a`, the fact that the memory representation -of a `UInt8` differs from a `Float64` also means that the CPU needs to handle them using two different -kinds of instructions. Since the required information is not available in the type, such decisions -have to be made at run-time. This slows performance. +of a [`UInt8`](@ref) differs from a [`Float64`](@ref) also means that the CPU needs to handle +them using two different kinds of instructions. Since the required information is not available +in the type, such decisions have to be made at run-time. This slows performance. You can do better by declaring the type of `a`. Here, we are focused on the case where `a` might be any one of several types, in which case the natural solution is to use parameters. For example: @@ -473,9 +473,9 @@ function foo(a::Array{Any,1}) end ``` -Here, we happened to know that the first element of `a` would be an `Int32`. Making an annotation -like this has the added benefit that it will raise a run-time error if the value is not of the -expected type, potentially catching certain bugs earlier. +Here, we happened to know that the first element of `a` would be an [`Int32`](@ref). Making +an annotation like this has the added benefit that it will raise a run-time error if the +value is not of the expected type, potentially catching certain bugs earlier. ### Declare types of keyword arguments @@ -1388,7 +1388,7 @@ code defined in `pos`. Starting at `2:`, the variable `y` is defined, and again annotated as a `Union` type. Next, we see that the compiler created the temporary variable `_var1` to hold the result of `y*x`. Because -a [`Float64`](@ref) times *either* an `Int64` or [`Float64`](@ref) yields a [`Float64`](@ref), +a [`Float64`](@ref) times *either* an [`Int64`](@ref) or `Float64` yields a `Float64`, all type-instability ends here. The net result is that `f(x::Float64)` will not be type-unstable in its output, even if some of the intermediate computations are type-unstable. diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index 4d4b9d5a0f1588..a1298af12de5bf 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -64,8 +64,8 @@ julia> typeof(ans) Int64 ``` -On 32-bit architectures, [`typeof(ans)`](@ref) will be `Int32`. You can convert an integer value -back to a `Char` just as easily: +On 32-bit architectures, [`typeof(ans)`](@ref) will be [`Int32`](@ref). You can convert an +integer value back to a `Char` just as easily: ```jldoctest julia> Char(120) @@ -778,8 +778,8 @@ for regular expressions containing quotation marks or newlines). ## [Byte Array Literals](@id man-byte-array-literals) Another useful non-standard string literal is the byte-array string literal: `b"..."`. This form -lets you use string notation to express literal byte arrays -- i.e. arrays of `UInt8` values. -The rules for byte array literals are the following: +lets you use string notation to express literal byte arrays -- i.e. arrays of +[`UInt8`](@ref) values. The rules for byte array literals are the following: * ASCII characters and ASCII escapes produce a single byte. * `\x` and octal escape sequences produce the *byte* corresponding to the escape value. diff --git a/doc/src/manual/style-guide.md b/doc/src/manual/style-guide.md index c4ac88ffc20a61..fccb5559d9272a 100644 --- a/doc/src/manual/style-guide.md +++ b/doc/src/manual/style-guide.md @@ -32,11 +32,12 @@ complex(float(x)) The second version will convert `x` to an appropriate type, instead of always the same type. This style point is especially relevant to function arguments. For example, don't declare an argument -to be of type `Int` or `Int32` if it really could be any integer, expressed with the abstract -type `Integer`. In fact, in many cases you can omit the argument type altogether, unless it is -needed to disambiguate from other method definitions, since a [`MethodError`](@ref) will be thrown -anyway if a type is passed that does not support any of the requisite operations. (This is known -as [duck typing](https://en.wikipedia.org/wiki/Duck_typing).) +to be of type `Int` or [`Int32`](@ref) if it really could be any integer, expressed with the abstract +type [`Integer`](@ref). In fact, in many cases you can omit the argument type altogether, +unless it is needed to disambiguate from other method definitions, since a +[`MethodError`](@ref) will be thrown anyway if a type is passed that does not support any +of the requisite operations. (This is known as +[duck typing](https://en.wikipedia.org/wiki/Duck_typing).) For example, consider the following definitions of a function `addone` that returns one plus its argument: @@ -356,7 +357,7 @@ julia> g(1) As you can see, the second version, where we used an `Int` literal, preserved the type of the input argument, while the first didn't. This is because e.g. `promote_type(Int, Float64) == Float64`, -and promotion happens with the multiplication. Similarly, `Rational` literals are less type disruptive +and promotion happens with the multiplication. Similarly, [`Rational`](@ref) literals are less type disruptive than [`Float64`](@ref) literals, but more disruptive than `Int`s: ```jldoctest diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 633ba5b47fac7b..da93e407f2cf26 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -133,18 +133,19 @@ system: they form the conceptual hierarchy which makes Julia's type system more of object implementations. Recall that in [Integers and Floating-Point Numbers](@ref), we introduced a variety of concrete -types of numeric values: `Int8`, `UInt8`, `Int16`, `UInt16`, `Int32`, `UInt32`, `Int64`, `UInt64`, -`Int128`, `UInt128`, `Float16`, [`Float32`](@ref), and [`Float64`](@ref). Although they have -different representation sizes, `Int8`, `Int16`, `Int32`, `Int64` and `Int128` all have in common -that they are signed integer types. Likewise `UInt8`, `UInt16`, `UInt32`, `UInt64` and `UInt128` -are all unsigned integer types, while `Float16`, [`Float32`](@ref) and [`Float64`](@ref) are distinct -in being floating-point types rather than integers. It is common for a piece of code to make sense, -for example, only if its arguments are some kind of integer, but not really depend on what particular -*kind* of integer. For example, the greatest common denominator algorithm works for all kinds -of integers, but will not work for floating-point numbers. Abstract types allow the construction -of a hierarchy of types, providing a context into which concrete types can fit. This allows you, -for example, to easily program to any type that is an integer, without restricting an algorithm -to a specific type of integer. +types of numeric values: [`Int8`](@ref), [`UInt8`](@ref), [`Int16`](@ref), [`UInt16`](@ref), +[`Int32`](@ref), [`UInt32`](@ref), [`Int64`](@ref), [`UInt64`](@ref), [`Int128`](@ref), +[`UInt128`](@ref), [`Float16`](@ref), [`Float32`](@ref), and [`Float64`](@ref). Although +they have different representation sizes, `Int8`, `Int16`, `Int32`, `Int64` and `Int128` +all have in common that they are signed integer types. Likewise `UInt8`, `UInt16`, `UInt32`, +`UInt64` and `UInt128` are all unsigned integer types, while `Float16`, `Float32` and +`Float64` are distinct in being floating-point types rather than integers. It is common for +a piece of code to make sense, for example, only if its arguments are some kind of integer, +but not really depend on what particular *kind* of integer. For example, the greatest common +denominator algorithm works for all kinds of integers, but will not work for floating-point +numbers. Abstract types allow the construction of a hierarchy of types, providing a context +into which concrete types can fit. This allows you, for example, to easily program to any type +that is an integer, without restricting an algorithm to a specific type of integer. Abstract types are declared using the `abstract type` keyword. The general syntaxes for declaring an abstract type are: @@ -175,13 +176,14 @@ abstract type Signed <: Integer end abstract type Unsigned <: Integer end ``` -The `Number` type is a direct child type of `Any`, and `Real` is its child. In turn, `Real` has -two children (it has more, but only two are shown here; we'll get to the others later): `Integer` -and `AbstractFloat`, separating the world into representations of integers and representations -of real numbers. Representations of real numbers include, of course, floating-point types, but -also include other types, such as rationals. Hence, `AbstractFloat` is a proper subtype of `Real`, -including only floating-point representations of real numbers. Integers are further subdivided -into `Signed` and `Unsigned` varieties. +The [`Number`](@ref) type is a direct child type of `Any`, and [`Real`](@ref) is its child. +In turn, `Real` has two children (it has more, but only two are shown here; we'll get to +the others later): [`Integer`](@ref) and [`AbstractFloat`](@ref), separating the world into +representations of integers and representations of real numbers. Representations of real +numbers include, of course, floating-point types, but also include other types, such as +rationals. Hence, `AbstractFloat` is a proper subtype of `Real`, including only +floating-point representations of real numbers. Integers are further subdivided into +[`Signed`](@ref) and [`Unsigned`](@ref) varieties. The `<:` operator in general means "is a subtype of", and, used in declarations like this, declares the right-hand type to be an immediate supertype of the newly declared type. It can also be used @@ -268,19 +270,21 @@ primitive type «name» <: «supertype» «bits» end The number of bits indicates how much storage the type requires and the name gives the new type a name. A primitive type can optionally be declared to be a subtype of some supertype. If a supertype is omitted, then the type defaults to having `Any` as its immediate supertype. The declaration -of `Bool` above therefore means that a boolean value takes eight bits to store, and has `Integer` -as its immediate supertype. Currently, only sizes that are multiples of 8 bits are supported. -Therefore, boolean values, although they really need just a single bit, cannot be declared to -be any smaller than eight bits. - -The types `Bool`, `Int8` and `UInt8` all have identical representations: they are eight-bit chunks -of memory. Since Julia's type system is nominative, however, they are not interchangeable despite -having identical structure. A fundamental difference between them is that they have different -supertypes: `Bool`'s direct supertype is `Integer`, `Int8`'s is `Signed`, and `UInt8`'s is `Unsigned`. -All other differences between `Bool`, `Int8`, and `UInt8` are matters of behavior -- the way functions -are defined to act when given objects of these types as arguments. This is why a nominative type -system is necessary: if structure determined type, which in turn dictates behavior, then it would -be impossible to make `Bool` behave any differently than `Int8` or `UInt8`. +of [`Bool`](@ref) above therefore means that a boolean value takes eight bits to store, and has +[`Integer`](@ref) as its immediate supertype. Currently, only sizes that are multiples of +8 bits are supported. Therefore, boolean values, although they really need just a single bit, +cannot be declared to be any smaller than eight bits. + +The types [`Bool`](@ref), [`Int8`](@ref) and [`UInt8`](@ref) all have identical representations: +they are eight-bit chunks of memory. Since Julia's type system is nominative, however, they +are not interchangeable despite having identical structure. A fundamental difference between +them is that they have different supertypes: [`Bool`](@ref)'s direct supertype is [`Integer`](@ref), +[`Int8`](@ref)'s is [`Signed`](@ref), and [`UInt8`](@ref)'s is [`Unsigned`](@ref). All other +differences between [`Bool`](@ref), [`Int8`](@ref), and [`UInt8`](@ref) are matters of +behavior -- the way functions are defined to act when given objects of these types as +arguments. This is why a nominative type system is necessary: if structure determined type, +which in turn dictates behavior, then it would be impossible to make [`Bool`](@ref) behave +any differently than [`Int8`](@ref) or [`UInt8`](@ref). ## Composite Types @@ -586,14 +590,16 @@ have different representations in memory: * An instance of `Point{Float64}` can be represented compactly and efficiently as an immediate pair of 64-bit values; - * An instance of `Point{Real}` must be able to hold any pair of instances of `Real`. Since objects - that are instances of `Real` can be of arbitrary size and structure, in practice an instance of - `Point{Real}` must be represented as a pair of pointers to individually allocated `Real` objects. + * An instance of `Point{Real}` must be able to hold any pair of instances of [`Real`](@ref). + Since objects that are instances of `Real` can be of arbitrary size and structure, in + practice an instance of `Point{Real}` must be represented as a pair of pointers to + individually allocated `Real` objects. The efficiency gained by being able to store `Point{Float64}` objects with immediate values is magnified enormously in the case of arrays: an `Array{Float64}` can be stored as a contiguous memory block of 64-bit floating-point values, whereas an `Array{Real}` must be an array of pointers -to individually allocated `Real` objects -- which may well be [boxed](https://en.wikipedia.org/wiki/Object_type_%28object-oriented_programming%29#Boxing) +to individually allocated [`Real`](@ref) objects -- which may well be +[boxed](https://en.wikipedia.org/wiki/Object_type_%28object-oriented_programming%29#Boxing) 64-bit floating-point values, but also might be arbitrarily large, complex objects, which are declared to be implementations of the `Real` abstract type. @@ -607,7 +613,7 @@ end ``` A correct way to define a method that accepts all arguments of type `Point{T}` where `T` is -a subtype of `Real` is: +a subtype of [`Real`](@ref) is: ```julia function norm(p::Point{<:Real}) @@ -784,8 +790,8 @@ possible types. In such situations, one can constrain the range of `T` like so: julia> abstract type Pointy{T<:Real} end ``` -With such a declaration, it is acceptable to use any type that is a subtype of `Real` in place -of `T`, but not types that are not subtypes of `Real`: +With such a declaration, it is acceptable to use any type that is a subtype of +[`Real`](@ref) in place of `T`, but not types that are not subtypes of `Real`: ```jldoctest realpointytype julia> Pointy{Float64} @@ -811,8 +817,8 @@ end ``` To give a real-world example of how all this parametric type machinery can be useful, here is -the actual definition of Julia's `Rational` immutable type (except that we omit the constructor -here for simplicity), representing an exact ratio of integers: +the actual definition of Julia's [`Rational`](@ref) immutable type (except that we omit the +constructor here for simplicity), representing an exact ratio of integers: ```julia struct Rational{T<:Integer} <: Real @@ -822,8 +828,8 @@ end ``` It only makes sense to take ratios of integer values, so the parameter type `T` is restricted -to being a subtype of `Integer`, and a ratio of integers represents a value on the real number -line, so any `Rational` is an instance of the `Real` abstraction. +to being a subtype of [`Integer`](@ref), and a ratio of integers represents a value on the +real number line, so any [`Rational`](@ref) is an instance of the [`Real`](@ref) abstraction. ### Tuple Types @@ -1008,21 +1014,22 @@ Using explicit `where` syntax, any subset of parameters can be fixed. For exampl 1-dimensional arrays can be written as `Array{T,1} where T`. Type variables can be restricted with subtype relations. -`Array{T} where T<:Integer` refers to all arrays whose element type is some kind of `Integer`. +`Array{T} where T<:Integer` refers to all arrays whose element type is some kind of +[`Integer`](@ref). The syntax `Array{<:Integer}` is a convenient shorthand for `Array{T} where T<:Integer`. Type variables can have both lower and upper bounds. -`Array{T} where Int<:T<:Number` refers to all arrays of `Number`s that are able to contain `Int`s -(since `T` must be at least as big as `Int`). +`Array{T} where Int<:T<:Number` refers to all arrays of [`Number`](@ref)s that are able to +contain `Int`s (since `T` must be at least as big as `Int`). The syntax `where T>:Int` also works to specify only the lower bound of a type variable, and `Array{>:Int}` is equivalent to `Array{T} where T>:Int`. Since `where` expressions nest, type variable bounds can refer to outer type variables. -For example `Tuple{T,Array{S}} where S<:AbstractArray{T} where T<:Real` refers to 2-tuples whose first -element is some `Real`, and whose second element is an `Array` of any kind of array whose element type -contains the type of the first tuple element. +For example `Tuple{T,Array{S}} where S<:AbstractArray{T} where T<:Real` refers to 2-tuples +whose first element is some [`Real`](@ref), and whose second element is an `Array` of any +kind of array whose element type contains the type of the first tuple element. -The `where` keyword itself can be nested inside a more complex declaration. For example, consider the -two types created by the following declarations: +The `where` keyword itself can be nested inside a more complex declaration. For example, +consider the two types created by the following declarations: ```jldoctest julia> const T1 = Array{Array{T,1} where T, 1} @@ -1056,8 +1063,8 @@ element type. Sometimes it is convenient to introduce a new name for an already expressible type. This can be done with a simple assignment statement. -For example, `UInt` is aliased to either `UInt32` or `UInt64` as is appropriate -for the size of pointers on the system: +For example, `UInt` is aliased to either [`UInt32`](@ref) or [`UInt64`](@ref) as is +appropriate for the size of pointers on the system: ```julia-repl # 32-bit system: @@ -1080,11 +1087,12 @@ end ``` Of course, this depends on what `Int` is aliased to -- but that is predefined to be the correct -type -- either `Int32` or `Int64`. +type -- either [`Int32`](@ref) or [`Int64`](@ref). -(Note that unlike `Int`, `Float` does not exist as a type alias for a specific sized `AbstractFloat`. -Unlike with integer registers, the floating point register sizes are specified by the IEEE-754 standard. -Whereas the size of `Int` reflects the size of a native pointer on that machine.) +(Note that unlike `Int`, `Float` does not exist as a type alias for a specific sized +[`AbstractFloat`](@ref). Unlike with integer registers, the floating point register sizes +are specified by the IEEE-754 standard. Whereas the size of `Int` reflects the size of a +native pointer on that machine.) ## Operations on Types @@ -1175,11 +1183,13 @@ julia> Polar(r::Real,Θ::Real) = Polar(promote(r,Θ)...) Polar ``` -Here, we've added a custom constructor function so that it can take arguments of different `Real` -types and promote them to a common type (see [Constructors](@ref man-constructors) and [Conversion and Promotion](@ref conversion-and-promotion)). -(Of course, we would have to define lots of other methods, too, to make it act like a `Number`, -e.g. `+`, `*`, `one`, `zero`, promotion rules and so on.) By default, instances of this type display -rather simply, with information about the type name and the field values, as e.g. `Polar{Float64}(3.0,4.0)`. +Here, we've added a custom constructor function so that it can take arguments of different +[`Real`](@ref) types and promote them to a common type (see [Constructors](@ref man-constructors) +and [Conversion and Promotion](@ref conversion-and-promotion)). +(Of course, we would have to define lots of other methods, too, to make it act like a +[`Number`](@ref), e.g. `+`, `*`, `one`, `zero`, promotion rules and so on.) By default, +instances of this type display rather simply, with information about the type name and +the field values, as e.g. `Polar{Float64}(3.0,4.0)`. If we want it to display instead as `3.0 * exp(4.0im)`, we would define the following method to print the object to a given output object `io` (representing a file, terminal, buffer, etcetera; @@ -1247,7 +1257,7 @@ julia> show(STDOUT, "text/html", Polar(3.0,4.0)) In Julia, you can't dispatch on a *value* such as `true` or `false`. However, you can dispatch on parametric types, and Julia allows you to include "plain bits" values (Types, Symbols, Integers, floating-point numbers, tuples, etc.) as type parameters. A common example is the dimensionality -parameter in `Array{T,N}`, where `T` is a type (e.g., `Float64`) but `N` is just an `Int`. +parameter in `Array{T,N}`, where `T` is a type (e.g., [`Float64`](@ref)) but `N` is just an `Int`. You can create your own custom types that take values as parameters, and use them to control dispatch of custom types. By way of illustration of this idea, let's introduce a parametric type, `Val{T}`, diff --git a/doc/src/stdlib/arrays.md b/doc/src/stdlib/arrays.md index cb3468061dbc40..2fc43f52bee532 100644 --- a/doc/src/stdlib/arrays.md +++ b/doc/src/stdlib/arrays.md @@ -1,28 +1,9 @@ # [Arrays](@id lib-arrays) -## Basic functions - -```@docs -Base.ndims -Base.size -Base.indices(::Any) -Base.indices(::AbstractArray, ::Any) -Base.length(::AbstractArray) -Base.eachindex -Base.linearindices -Base.IndexStyle -Base.countnz -Base.conj! -Base.stride -Base.strides -Base.ind2sub -Base.sub2ind -Base.LinAlg.checksquare -``` - -## Constructors +## Constructors and Types ```@docs +Core.AbstractArray Core.Array Base.getindex(::Type, ::Any...) Base.zeros @@ -41,6 +22,26 @@ Base.Random.randsubseq Base.Random.randsubseq! ``` +## Basic functions + +```@docs +Base.ndims +Base.size +Base.indices(::Any) +Base.indices(::AbstractArray, ::Any) +Base.length(::AbstractArray) +Base.eachindex +Base.linearindices +Base.IndexStyle +Base.countnz +Base.conj! +Base.stride +Base.strides +Base.ind2sub +Base.sub2ind +Base.LinAlg.checksquare +``` + ## Broadcast and vectorization See also the [dot syntax for vectorizing functions](@ref man-vectorized); diff --git a/doc/src/stdlib/collections.md b/doc/src/stdlib/collections.md index 29d8c38f3b1a8e..1ab225a8542088 100644 --- a/doc/src/stdlib/collections.md +++ b/doc/src/stdlib/collections.md @@ -39,7 +39,7 @@ Fully implemented by: * `UnitRange` * `Tuple` * `Number` - * `AbstractArray` + * [`AbstractArray`](@ref) * [`IntSet`](@ref) * [`ObjectIdDict`](@ref) * [`Dict`](@ref) @@ -63,7 +63,7 @@ Fully implemented by: * `UnitRange` * `Tuple` * `Number` - * `AbstractArray` + * [`AbstractArray`](@ref) * [`IntSet`](@ref) * [`ObjectIdDict`](@ref) * [`Dict`](@ref) @@ -145,7 +145,7 @@ Fully implemented by: * [`Array`](@ref) * [`BitArray`](@ref) - * `AbstractArray` + * [`AbstractArray`](@ref) * `SubArray` * [`ObjectIdDict`](@ref) * [`Dict`](@ref) diff --git a/doc/src/stdlib/file.md b/doc/src/stdlib/file.md index e0f5874d0d5277..26e9f9d5779286 100644 --- a/doc/src/stdlib/file.md +++ b/doc/src/stdlib/file.md @@ -49,7 +49,7 @@ Base.Filesystem.dirname Base.Filesystem.basename Base.@__FILE__ Base.@__DIR__ -@__LINE__ +Base.@__LINE__ Base.Filesystem.isabspath Base.Filesystem.isdirpath Base.Filesystem.joinpath diff --git a/doc/src/stdlib/linalg.md b/doc/src/stdlib/linalg.md index bee85bb1522274..0f415013c51dcb 100644 --- a/doc/src/stdlib/linalg.md +++ b/doc/src/stdlib/linalg.md @@ -154,13 +154,13 @@ Base.At_rdiv_Bt In Julia (as in much of scientific computation), dense linear-algebra operations are based on the [LAPACK library](http://www.netlib.org/lapack/), which in turn is built on top of basic linear-algebra -building-blocks known as the [BLAS](http://www.netlib.org/blas/). There are highly optimized +building-blocks known as the [BLAS](http://www.netlib.org/blas/). There are highly optimized implementations of BLAS available for every computer architecture, and sometimes in high-performance linear algebra routines it is useful to call the BLAS functions directly. `Base.LinAlg.BLAS` provides wrappers for some of the BLAS functions. Those BLAS functions that overwrite one of the input arrays have names ending in `'!'`. Usually, a BLAS function has -four methods defined, for `Float64`, `Float32`, `Complex128`, and `Complex64` arrays. +four methods defined, for [`Float64`](@ref), [`Float32`](@ref), `Complex128`, and `Complex64` arrays. ### [BLAS Character Arguments](@id stdlib-blas-chars) Many BLAS functions accept arguments that determine whether to transpose an argument (`trans`), @@ -245,8 +245,8 @@ Base.LinAlg.I `Base.LinAlg.LAPACK` provides wrappers for some of the LAPACK functions for linear algebra. Those functions that overwrite one of the input arrays have names ending in `'!'`. -Usually a function has 4 methods defined, one each for `Float64`, `Float32`, `Complex128` and -`Complex64` arrays. +Usually a function has 4 methods defined, one each for [`Float64`](@ref), [`Float32`](@ref), +`Complex128` and `Complex64` arrays. Note that the LAPACK API provided by Julia can and will change in the future. Since this API is not user-facing, there is no commitment to support/deprecate this specific set of functions in diff --git a/doc/src/stdlib/numbers.md b/doc/src/stdlib/numbers.md index 36ee7e5634d2ff..af00def34e64ec 100644 --- a/doc/src/stdlib/numbers.md +++ b/doc/src/stdlib/numbers.md @@ -2,22 +2,40 @@ ## Standard Numeric Types - * `Bool` - * `Int8` - * `UInt8` - * `Int16` - * `UInt16` - * `Int32` - * `UInt32` - * `Int64` - * `UInt64` - * `Int128` - * `UInt128` - * `Float16` - * `Float32` - * `Float64` - * `Complex64` - * `Complex128` +### Abstract number types + +```@docs +Core.Number +Core.Real +Core.AbstractFloat +Core.Integer +Core.Signed +Core.Unsigned +``` + +### Concrete number types + +```@docs +Core.Float16 +Core.Float32 +Core.Float64 +Base.BigFloat +Core.Bool +Core.Int8 +Core.UInt8 +Core.Int16 +Core.UInt16 +Core.Int32 +Core.UInt32 +Core.Int64 +Core.UInt64 +Core.Int128 +Core.UInt128 +Base.BigInt +Base.Complex +Base.Rational +Base.Irrational +``` ## Data Formats @@ -73,10 +91,10 @@ Base.nextfloat Base.prevfloat Base.isinteger Base.isreal -Core.Float32 -Core.Float64 -Base.GMP.BigInt -Base.MPFR.BigFloat +Core.Float32(::Any) +Core.Float64(::Any) +Base.GMP.BigInt(::Any) +Base.MPFR.BigFloat(::Any) Base.Rounding.rounding Base.Rounding.setrounding(::Type, ::Any) Base.Rounding.setrounding(::Function, ::Type, ::RoundingMode) @@ -99,7 +117,8 @@ Base.iseven ## BigFloats -The `BigFloat` type implements arbitrary-precision floating-point arithmetic using the [GNU MPFR library](http://www.mpfr.org/). +The [`BigFloat`](@ref) type implements arbitrary-precision floating-point arithmetic using +the [GNU MPFR library](http://www.mpfr.org/). ```@docs Base.precision @@ -125,10 +144,12 @@ dimension specifications `dims...` (which can be given as a tuple) to generate a values. A `MersenneTwister` or `RandomDevice` RNG can generate random numbers of the following types: -`Float16`, `Float32`, `Float64`, `Bool`, `Int8`, `UInt8`, `Int16`, `UInt16`, `Int32`, `UInt32`, -`Int64`, `UInt64`, `Int128`, `UInt128`, `BigInt` (or complex numbers of those types). Random floating -point numbers are generated uniformly in ``[0, 1)``. As `BigInt` represents unbounded integers, -the interval must be specified (e.g. `rand(big(1:6))`). +[`Float16`](@ref), [`Float32`](@ref), [`Float64`](@ref), [`Bool`](@ref), [`Int8`](@ref), +[`UInt8`](@ref), [`Int16`](@ref), [`UInt16`](@ref), [`Int32`](@ref), [`UInt32`](@ref), +[`Int64`](@ref), [`UInt64`](@ref), [`Int128`](@ref), [`UInt128`](@ref), [`BigInt`](@ref) +(or complex numbers of those types). Random floating point numbers are generated uniformly +in ``[0, 1)``. As `BigInt` represents unbounded integers, the interval must be specified +(e.g. `rand(big(1:6))`). ```@docs Base.Random.srand diff --git a/examples/clustermanager/simple/UnixDomainCM.jl b/examples/clustermanager/simple/UnixDomainCM.jl index e3a1f7f9d350aa..afffa610a21b95 100644 --- a/examples/clustermanager/simple/UnixDomainCM.jl +++ b/examples/clustermanager/simple/UnixDomainCM.jl @@ -12,7 +12,8 @@ function launch(manager::UnixDomainCM, params::Dict, launched::Array, c::Conditi for i in 1:manager.np sockname = tempname() try - cmd = `$(params[:exename]) --startup-file=no $(@__FILE__) udwrkr $sockname $cookie` + __file__ = @__FILE__ + cmd = `$(params[:exename]) --startup-file=no $__file__ udwrkr $sockname $cookie` pobj = open(cmd) wconfig = WorkerConfig() diff --git a/examples/clustermanager/simple/test_simple.jl b/examples/clustermanager/simple/test_simple.jl index 57e8a8a0f28fe8..2460eadd77b537 100644 --- a/examples/clustermanager/simple/test_simple.jl +++ b/examples/clustermanager/simple/test_simple.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -cmanpath = joinpath(dirname(@__FILE__), "UnixDomainCM.jl") +cmanpath = joinpath(@__DIR__, "UnixDomainCM.jl") include(cmanpath) npids = addprocs(UnixDomainCM(2)) diff --git a/src/ast.c b/src/ast.c index 6b9ac084649ff0..ed44ab1509d092 100644 --- a/src/ast.c +++ b/src/ast.c @@ -176,19 +176,42 @@ value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t narg { JL_TIMING(MACRO_INVOCATION); jl_ptls_t ptls = jl_get_ptls_states(); - if (nargs < 1) - argcount(fl_ctx, "invoke-julia-macro", nargs, 1); + if (nargs < 2) // macro name and location + argcount(fl_ctx, "invoke-julia-macro", nargs, 2); jl_method_instance_t *mfunc = NULL; jl_value_t **margs; // Reserve one more slot for the result JL_GC_PUSHARGS(margs, nargs + 1); int i; - for(i=1; i < nargs; i++) margs[i] = scm_to_julia(fl_ctx, args[i], 1); + margs[0] = scm_to_julia(fl_ctx, args[0], 1); + // __source__ argument + jl_value_t *lno = scm_to_julia(fl_ctx, args[1], 1); + margs[1] = lno; + if (jl_is_expr(lno) && ((jl_expr_t*)lno)->head == line_sym) { + jl_value_t *file = jl_nothing; + jl_value_t *line = NULL; + switch (jl_expr_nargs(lno)) { + case 2: + file = jl_exprarg(lno, 1); // file + JL_FALLTHROUGH; + case 1: + line = jl_exprarg(lno, 0); // line + JL_FALLTHROUGH; + default: ; + } + if (line == NULL) + line = jl_box_long(0); + margs[1] = jl_new_struct(jl_linenumbernode_type, line, file); + } + else if (!jl_typeis(lno, jl_linenumbernode_type)) { + margs[1] = jl_new_struct(jl_linenumbernode_type, jl_box_long(0), jl_nothing); + } + for (i = 2; i < nargs; i++) + margs[i] = scm_to_julia(fl_ctx, args[i], 1); jl_value_t *result = NULL; size_t world = jl_get_ptls_states()->world_age; JL_TRY { - margs[0] = scm_to_julia(fl_ctx, args[0], 1); margs[0] = jl_toplevel_eval(margs[0]); mfunc = jl_method_lookup(jl_gf_mtable(margs[0]), margs, nargs, 1, world); if (mfunc == NULL) { @@ -560,10 +583,13 @@ static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, int eo) else n++; if (!eo) { - if (sym == line_sym && n==1) { + if (sym == line_sym && (n == 1 || n == 2)) { jl_value_t *linenum = scm_to_julia_(fl_ctx, car_(e), 0); - JL_GC_PUSH1(&linenum); - jl_value_t *temp = jl_new_struct(jl_linenumbernode_type, linenum); + jl_value_t *file = jl_nothing; + JL_GC_PUSH2(&linenum, &file); + if (n == 2) + file = scm_to_julia_(fl_ctx, car_(cdr_(e)), 0); + jl_value_t *temp = jl_new_struct(jl_linenumbernode_type, linenum, file); JL_GC_POP(); return temp; } @@ -724,8 +750,16 @@ static value_t julia_to_scm_(fl_context_t *fl_ctx, jl_value_t *v) // shouldn't allocate in this case. if (jl_typeis(v, jl_labelnode_type)) return julia_to_list2(fl_ctx, (jl_value_t*)label_sym, jl_fieldref(v,0)); - if (jl_typeis(v, jl_linenumbernode_type)) - return julia_to_list2(fl_ctx, (jl_value_t*)line_sym, jl_fieldref(v,0)); + if (jl_typeis(v, jl_linenumbernode_type)) { + jl_value_t *file = jl_fieldref(v,1); // non-allocating + jl_value_t *line = jl_fieldref(v,0); // allocating + value_t args = julia_to_list2(fl_ctx, line, file); + fl_gc_handle(fl_ctx, &args); + value_t hd = julia_to_scm_(fl_ctx, (jl_value_t*)line_sym); + value_t scmv = fl_cons(fl_ctx, hd, args); + fl_free_gc_handles(fl_ctx, 1); + return scmv; + } if (jl_typeis(v, jl_gotonode_type)) return julia_to_list2(fl_ctx, (jl_value_t*)goto_sym, jl_fieldref(v,0)); if (jl_typeis(v, jl_quotenode_type)) diff --git a/src/ccall.cpp b/src/ccall.cpp index 30af151ebc872d..eeb2bb2d833df7 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1787,18 +1787,26 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) jl_value_t *frt = expr_type(args[6], ctx); if (f && (jl_is_type_type((jl_value_t*)frt) && !jl_has_free_typevars(jl_tparam0(frt)))) { fargt = static_eval(args[8], ctx, true, true); - if (fargt) { - if (jl_is_tuple(fargt)) { - // TODO: maybe deprecation warning, better checking - fargt = (jl_value_t*)jl_apply_tuple_type_v((jl_value_t**)jl_data_ptr(fargt), jl_nfields(fargt)); - } - } - else { + if (!fargt) { fargt = expr_type(args[8], ctx); - if (jl_is_type_type((jl_value_t*)fargt)) + if (jl_is_type_type((jl_value_t*)fargt)) { fargt = jl_tparam0(fargt); + if (jl_has_free_typevars(fargt) || !jl_is_tuple_type(fargt)) { + fargt = nullptr; + } + } + else { + fargt = nullptr; + } + } + else if (jl_is_tuple(fargt)) { + // TODO: maybe deprecation warning, better checking + fargt = (jl_value_t*)jl_apply_tuple_type_v((jl_value_t**)jl_data_ptr(fargt), jl_nfields(fargt)); } - if (jl_is_tuple_type(fargt) && jl_is_leaf_type(fargt)) { + else if (!jl_is_tuple_type(fargt)) { + fargt = nullptr; + } + if (fargt) { frt = jl_tparam0(frt); Value *llvmf = NULL; JL_TRY { diff --git a/src/cgmemmgr.cpp b/src/cgmemmgr.cpp index ea59a6a3c42c77..6b2f43ebffdcf2 100644 --- a/src/cgmemmgr.cpp +++ b/src/cgmemmgr.cpp @@ -264,9 +264,9 @@ static void *alloc_shared_page(size_t size, size_t *id, bool exec) #ifdef _OS_LINUX_ // Using `/proc/self/mem`, A.K.A. Keno's remote memory manager. -static int self_mem_fd = -1; - -static int init_self_mem() +// Do not call this directly. +// Use `get_self_mem_fd` which has a guard to call this only once. +static int _init_self_mem() { struct utsname kernel; uname(&kernel); @@ -288,22 +288,34 @@ static int init_self_mem() return -1; fcntl(fd, F_SETFD, FD_CLOEXEC); #endif - // buffer to check if write works; - volatile uint64_t buff = 0; - uint64_t v = 0x12345678; - int ret = pwrite(fd, (void*)&v, sizeof(uint64_t), (uintptr_t)&buff); - if (ret != sizeof(uint64_t) || buff != 0x12345678) { + + // Check if we can write to a RX page + void *test_pg = mmap(nullptr, jl_page_size, PROT_READ | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + // We can ignore this though failure to allocate executable memory would be a bigger problem. + assert(test_pg != MAP_FAILED && "Cannot allocate executable memory"); + + const uint64_t v = 0xffff000012345678u; + int ret = pwrite(fd, (const void*)&v, sizeof(uint64_t), (uintptr_t)test_pg); + if (ret != sizeof(uint64_t) || *(volatile uint64_t*)test_pg != v) { + munmap(test_pg, jl_page_size); close(fd); return -1; } - self_mem_fd = fd; + munmap(test_pg, jl_page_size); + return fd; +} + +static int get_self_mem_fd() +{ + static int fd = _init_self_mem(); return fd; } static void write_self_mem(void *dest, void *ptr, size_t size) { while (size > 0) { - ssize_t ret = pwrite(self_mem_fd, ptr, size, (uintptr_t)dest); + ssize_t ret = pwrite(get_self_mem_fd(), ptr, size, (uintptr_t)dest); if ((size_t)ret == size) return; if (ret == -1 && (errno == EAGAIN || errno == EINTR)) @@ -657,7 +669,7 @@ class SelfMemAllocator : public ROAllocator { : ROAllocator(), temp_buff() { - assert(self_mem_fd != -1); + assert(get_self_mem_fd() != -1); } void finalize() override { @@ -717,7 +729,7 @@ class RTDyldMemoryManagerJL : public SectionMemoryManager { code_allocated(false) { #ifdef _OS_LINUX_ - if (!ro_alloc && init_self_mem() != -1) { + if (!ro_alloc && get_self_mem_fd() != -1) { ro_alloc.reset(new SelfMemAllocator()); exe_alloc.reset(new SelfMemAllocator()); } diff --git a/src/codegen.cpp b/src/codegen.cpp index 552a70a1a703fa..82685cd2f57a90 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4083,13 +4083,13 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) return emit_getfield((jl_value_t*)jl_globalref_mod(expr), jl_globalref_name(expr), ctx); } if (jl_is_labelnode(expr)) { - jl_error("Labelnode in value position"); + jl_error("LabelNode in value position"); } if (jl_is_linenode(expr)) { - jl_error("Linenode in value position"); + jl_error("LineNumberNode in value position"); } if (jl_is_gotonode(expr)) { - jl_error("Gotonode in value position"); + jl_error("GotoNode in value position"); } if (!jl_is_expr(expr)) { int needroot = true; diff --git a/src/gf.c b/src/gf.c index 599eabd62b9e15..683b11bc1d24c3 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1162,10 +1162,10 @@ static int check_ambiguous_visitor(jl_typemap_entry_t *oldentry, struct typemap_ jl_static_show_func_sig(s, isect); jl_printf(s, "\nbefore the new definition.\n"); } - return 1; // there may be multiple ambiguities, keep going } - else if (closure->after) { + if (!msp || closure->after) { // record that this method definition is being partially replaced + // (either with a real definition, or an ambiguity error) if (closure->shadowed == NULL) { closure->shadowed = oldentry->func.value; } diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 804361fb85ee3e..54a950a4ec99d0 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -161,6 +161,7 @@ void addOptimizationPasses(PassManager *PM) // list of passes from vmkit PM->add(createCFGSimplificationPass()); // Clean up disgusting code PM->add(createPromoteMemoryToRegisterPass()); // Kill useless allocas + PM->add(createMemCpyOptPass()); // hopefully these functions (from llvmcall) don't try to interact with the Julia runtime // or have anything that might corrupt the createLowerPTLSPass pass diff --git a/src/jlfrontend.scm b/src/jlfrontend.scm index 5c973bacd83f05..28f62d2525fb01 100644 --- a/src/jlfrontend.scm +++ b/src/jlfrontend.scm @@ -50,6 +50,7 @@ (cdr e)))) tab))) +;; find variables that should be forced to be global in a toplevel expr (define (find-possible-globals e) (table.keys (find-possible-globals- e (table)))) @@ -59,19 +60,6 @@ (define (some-gensym? x) (or (gensym? x) (memq x *gensyms*))) -;; find variables that should be forced to be global in a toplevel expr -(define (toplevel-expr-globals e) - (diff - (delete-duplicates - (append - ;; vars assigned at the outer level - (filter (lambda (x) (not (some-gensym? x))) (find-assigned-vars e '())) - ;; vars declared const or global outside any scope block - (find-decls 'const e) - (find-decls 'global e) - ;; vars assigned anywhere, if they have been defined as global - (filter defined-julia-global (find-possible-globals e)))) - (find-decls 'local e))) ;; return a lambda expression representing a thunk for a top-level expression ;; note: expansion of stuff inside module is delayed, so the contents obey @@ -81,11 +69,22 @@ (if (and (pair? ex0) (eq? (car ex0) 'toplevel)) ex0 (let* ((ex (julia-expand0 ex0)) - (gv (toplevel-expr-globals ex)) + (lv (find-decls 'local ex)) + (gv (diff (delete-duplicates + (append (find-decls 'const ex) ;; convert vars declared const outside any scope block to outer-globals + (find-decls 'global ex) ;; convert vars declared global outside any scope block to outer-globals + ;; vars assigned at the outer level + (filter (lambda (x) (not (some-gensym? x))) + (find-assigned-vars ex '())))) + lv)) + ;; vars assigned anywhere, if they have not been explicitly defined + (existing-gv (filter (lambda (x) (and (not (or (memq x lv) (memq x gv))) (defined-julia-global x))) + (find-possible-globals ex))) (th (julia-expand1 `(lambda () () (scope-block - (block ,@(map (lambda (v) `(implicit-global ,v)) gv) + (block ,@(map (lambda (v) `(implicit-global ,v)) existing-gv) + ,@(map (lambda (v) `(implicit-global ,v)) gv) ,ex)))))) (if (and (null? (cdadr (caddr th))) (= 0 (cadddr (caddr th)))) diff --git a/src/jltypes.c b/src/jltypes.c index bc130b86cf63f2..91a579b36ae50f 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1850,8 +1850,8 @@ void jl_init_types(void) jl_linenumbernode_type = jl_new_datatype(jl_symbol("LineNumberNode"), jl_any_type, jl_emptysvec, - jl_perm_symsvec(1, "line"), - jl_svec(1, jl_long_type), 0, 0, 1); + jl_perm_symsvec(2, "line", "file"), + jl_svec(2, jl_long_type, jl_any_type), 0, 0, 2); jl_labelnode_type = jl_new_datatype(jl_symbol("LabelNode"), jl_any_type, jl_emptysvec, diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 1faa88c53dc33c..2cb278799726d5 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -359,10 +359,10 @@ ((eq? pred char-bin?) (fix-uint-neg neg (sized-uint-literal n s 1))) (is-float32-literal (numchk n s) (float n)) (n (if (and (integer? n) (> n 9223372036854775807)) - `(macrocall @int128_str ,s) + `(macrocall @int128_str (null) ,s) n)) - ((within-int128? s) `(macrocall @int128_str ,s)) - (else `(macrocall @big_str ,s)))))) + ((within-int128? s) `(macrocall @int128_str (null) ,s)) + (else `(macrocall @big_str (null) ,s)))))) (define (fix-uint-neg neg n) (if neg @@ -378,7 +378,7 @@ ((<= l 16) (numchk n s) (uint16 n)) ((<= l 32) (numchk n s) (uint32 n)) ((<= l 64) (numchk n s) (uint64 n)) - ((<= l 128) `(macrocall @uint128_str ,s)) + ((<= l 128) `(macrocall @uint128_str (null) ,s)) (else (error "Hex or binary literal too large for UInt128"))))) (define (sized-uint-oct-literal n s) @@ -391,7 +391,7 @@ (else (uint64 n))) (begin (if (equal? s "0o") (numchk n s)) (if (oct-within-uint128? s) - `(macrocall @uint128_str ,s) + `(macrocall @uint128_str (null) ,s) (error "Octal literal too large for UInt128")))))) (define (strip-leading-0s s) @@ -868,11 +868,11 @@ (define (maybe-negate op num) (if (eq? op '-) (if (large-number? num) - (if (eqv? (caddr num) "-170141183460469231731687303715884105728") - `(macrocall @big_str "170141183460469231731687303715884105728") - `(,(car num) ,(cadr num) ,(string.tail (caddr num) 1))) + (if (eqv? (cadddr num) "-170141183460469231731687303715884105728") + `(macrocall @big_str (null) "170141183460469231731687303715884105728") + `(,(car num) ,(cadr num) ,(caddr num) ,(string.tail (cadddr num) 1))) (if (= num -9223372036854775808) - `(macrocall @int128_str "9223372036854775808") + `(macrocall @int128_str (null) "9223372036854775808") (- num))) num)) @@ -1112,7 +1112,7 @@ (else (let ((name (parse-atom s))) (if (and (pair? name) (eq? (car name) 'macrocall)) - `(macrocall (|.| ,ex (quote ,(cadr name))) + `(macrocall (|.| ,ex (quote ,(cadr name))) ; move macrocall outside by rewriting A.@B as @A.B ,@(cddr name)) `(|.| ,ex (quote ,name)))))))) ((|.'| |'|) @@ -1129,16 +1129,17 @@ (not (operator? ex)) (not (ts:space? s))) ;; custom string and command literals; x"s" => @x_str "s" - (let* ((macstr (begin (take-token s) + (let* ((startloc (line-number-node s)) + (macstr (begin (take-token s) (parse-raw-literal s t))) (nxt (peek-token s)) (macname (macroify-name ex (macsuffix t)))) (if (and (symbol? nxt) (not (operator? nxt)) (not (ts:space? s))) ;; string literal suffix, "s"x - (loop `(macrocall ,macname ,macstr + (loop `(macrocall ,macname ,startloc ,macstr ,(string (take-token s)))) - (loop `(macrocall ,macname ,macstr)))) + (loop `(macrocall ,macname ,startloc ,macstr)))) ex)) (else ex)))))) @@ -2134,26 +2135,27 @@ ((eqv? t #\@) (take-token s) (with-space-sensitive - (let ((head (if (eq? (peek-token s) '|.|) + (let ((startloc (line-number-node s)) + (head (if (eq? (peek-token s) '|.|) (begin (take-token s) '__dot__) (parse-unary-prefix s)))) - (if (eq? head '__LINE__) - (input-port-line (ts:port s)) - (begin - (peek-token s) - (if (ts:space? s) - `(macrocall ,(macroify-name head) - ,@(parse-space-separated-exprs s)) - (let ((call (parse-call-chain s head #t))) - (if (and (pair? call) (eq? (car call) 'call)) - `(macrocall ,(macroify-name (cadr call)) ,@(cddr call)) - `(macrocall ,(macroify-name call) - ,@(parse-space-separated-exprs s)))))))))) - + (peek-token s) + (if (ts:space? s) + `(macrocall ,(macroify-name head) + ,startloc + ,@(parse-space-separated-exprs s)) + (let ((call (parse-call-chain s head #t))) + (if (and (pair? call) (eq? (car call) 'call)) + `(macrocall ,(macroify-name (cadr call)) + ,startloc + ,@(cddr call)) + `(macrocall ,(macroify-name call) + ,startloc + ,@(parse-space-separated-exprs s)))))))) ;; command syntax ((eqv? t #\`) (take-token s) - `(macrocall @cmd ,(parse-raw-literal s #\`))) + `(macrocall @cmd ,(line-number-node s) ,(parse-raw-literal s #\`))) ((or (string? t) (number? t) (large-number? t)) (take-token s)) @@ -2179,16 +2181,20 @@ (and (pair? e) (eq? 'string (car e))) ; string interpolation (and (length= e 3) (eq? (car e) 'macrocall) (simple-string-literal? (caddr e)) + (eq? (cadr e) '@doc_str)) + (and (length= e 4) (eq? (car e) 'macrocall) + (simple-string-literal? (cadddr e)) (eq? (cadr e) '@doc_str)))) (define (parse-docstring s production) - (let* ((ex (production s))) + (let ((startloc (line-number-node s)) ; be sure to use the line number from the head of the docstring + (ex (production s))) (if (and (doc-string-literal? ex) (let loop ((t (peek-token s))) (cond ((closing-token? t) #f) ((newline? t) (take-token s) (loop (peek-token s))) (else #t)))) - `(macrocall (core @doc) ,ex ,(production s)) + `(macrocall (core @doc) ,startloc ,ex ,(production s)) ex))) ;; --- main entry point --- diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 86ed90c300ac66..7f9a5085f2a971 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1162,6 +1162,7 @@ (error "macros cannot accept keyword arguments")) (expand-forms `(function (call ,(symbol (string #\@ (cadr (cadr e)))) + (|::| __source__ (core LineNumberNode)) ,@(map (lambda (v) (if (symbol? v) `(|::| ,v (core ANY)) @@ -2500,7 +2501,7 @@ ;; 3. variables assigned inside this scope-block that don't exist in outer ;; scopes ;; returns lambdas in the form (lambda (args...) (locals...) body) -(define (resolve-scopes- e env implicitglobals lam renames newlam) +(define (resolve-scopes- e env outerglobals implicitglobals lam renames newlam) (cond ((symbol? e) (let ((r (assq e renames))) (if r (cdr r) e))) ;; return the renaming for e, or e ((or (not (pair? e)) (quoted? e) (memq (car e) '(toplevel global))) e) @@ -2511,10 +2512,11 @@ (let* ((lv (lam:vars e)) (env (append lv env)) (body (resolve-scopes- (lam:body e) env - ;; don't propagate implicit globals - ;; issue #7234 + ;; don't propagate implicit or outer globals + '() '() e + ;; remove renames corresponding to local variables from the environment (filter (lambda (ren) (not (memq (car ren) lv))) renames) #t))) @@ -2522,17 +2524,16 @@ ((eq? (car e) 'scope-block) (let* ((blok (cadr e)) ;; body of scope-block expression (other-locals (if lam (caddr lam) '())) ;; locals that are explicitly part of containing lambda expression - (iglo (find-decls 'implicit-global blok)) ;; implicitly defined globals used in blok + (iglo (find-decls 'implicit-global blok)) ;; globals defined implicitly outside blok (glob (diff (find-global-decls blok) iglo)) ;; all globals declared in blok (vars-def (check-dups (find-local-def-decls blok) '())) (locals-declared (check-dups (find-local-decls blok) vars-def)) - (locals-implicit (diff (implicit-locals - blok - ;; being declared global prevents a variable - ;; assignment from introducing a local - (append env glob implicitglobals iglo) - (append glob iglo)) - vars-def)) + (locals-implicit (implicit-locals + blok + ;; being declared global prevents a variable + ;; assignment from introducing a local + (append env glob iglo outerglobals locals-declared vars-def) + (append glob iglo))) (vars (delete-duplicates (append! locals-declared locals-implicit))) (all-vars (append vars vars-def)) (need-rename? @@ -2551,26 +2552,22 @@ (renamed (map named-gensy need-rename)) (renamed-def (map named-gensy need-rename-def)) (new-env (append all-vars glob env)) ;; all variables declared in or outside blok - (new-iglo-table ;; initial list of implicit globals from outside blok which aren't part of the local vars - (let ((tab (table))) - (for-each (lambda (v) (if (not (memq v all-vars)) (put! tab v #t))) iglo) - (for-each (lambda (v) (if (not (memq v all-vars)) (put! tab v #t))) implicitglobals) - tab)) - (new-iglo (table.keys ;; compute list of all globals used implicitly in blok - (unbound-vars blok - new-env ;; list of everything else - new-iglo-table))) + ;; compute list of all globals used implicitly in blok (need renames) + (new-iglo (table.keys (unbound-vars blok + new-env ;; list of everything else + (table)))) ;; combine the list of new renamings with the inherited list (new-renames (append (map cons need-rename renamed) ;; map from definition name -> gensym name (map cons need-rename-def renamed-def) (map (lambda (g) (cons g `(outerref ,g))) new-iglo) (filter (lambda (ren) ;; old renames list, with anything in vars removed - (not (or (memq (car ren) all-vars) - (memq (car ren) iglo) - (memq (car ren) implicitglobals) - (memq (car ren) glob)))) + (let ((var (car ren))) + (not (or (memq var all-vars) ;; remove anything new + (memq var implicitglobals) ;; remove anything only added implicitly in the last scope block + (memq var glob))))) ;; remove anything that's now global renames))) - (body (resolve-scopes- blok new-env new-iglo lam new-renames #f)) + (new-oglo (append iglo outerglobals)) ;; list of all outer-globals from outside blok + (body (resolve-scopes- blok new-env new-oglo new-iglo lam new-renames #f)) (real-new-vars (append (diff vars need-rename) renamed)) (real-new-vars-def (append (diff vars-def need-rename-def) renamed-def))) (for-each (lambda (v) @@ -2590,18 +2587,18 @@ (error "module expression not at top level")) ((eq? (car e) 'break-block) `(break-block ,(cadr e) ;; ignore type symbol of break-block expression - ,(resolve-scopes- (caddr e) env implicitglobals lam renames #f))) ;; body of break-block expression + ,(resolve-scopes- (caddr e) env outerglobals implicitglobals lam renames #f))) ;; body of break-block expression ((eq? (car e) 'with-static-parameters) `(with-static-parameters ;; ignore list of sparams in break-block expression - ,(resolve-scopes- (cadr e) env implicitglobals lam renames #f) + ,(resolve-scopes- (cadr e) env outerglobals implicitglobals lam renames #f) ,@(cddr e))) ;; body of break-block expression (else (cons (car e) (map (lambda (x) - (resolve-scopes- x env implicitglobals lam renames #f)) + (resolve-scopes- x env outerglobals implicitglobals lam renames #f)) (cdr e)))))) -(define (resolve-scopes e) (resolve-scopes- e '() '() #f '() #f)) +(define (resolve-scopes e) (resolve-scopes- e '() '() '() #f '() #f)) ;; pass 3: analyze variables diff --git a/src/julia.h b/src/julia.h index 4b8439fb11852e..d25c67a3a2d2d6 100644 --- a/src/julia.h +++ b/src/julia.h @@ -741,17 +741,18 @@ STATIC_INLINE void jl_array_uint8_set(void *a, size_t i, uint8_t x) #define jl_exprargset(e, n, v) jl_array_ptr_set(((jl_expr_t*)(e))->args, n, v) #define jl_expr_nargs(e) jl_array_len(((jl_expr_t*)(e))->args) -#define jl_fieldref(s,i) jl_get_nth_field(((jl_value_t*)s),i) +#define jl_fieldref(s,i) jl_get_nth_field(((jl_value_t*)(s)),i) #define jl_nfields(v) jl_datatype_nfields(jl_typeof(v)) // Not using jl_fieldref to avoid allocations -#define jl_linenode_line(x) (((intptr_t*)x)[0]) -#define jl_labelnode_label(x) (((intptr_t*)x)[0]) -#define jl_slot_number(x) (((intptr_t*)x)[0]) -#define jl_typedslot_get_type(x) (((jl_value_t**)x)[1]) -#define jl_gotonode_label(x) (((intptr_t*)x)[0]) -#define jl_globalref_mod(s) (*(jl_module_t**)s) -#define jl_globalref_name(s) (((jl_sym_t**)s)[1]) +#define jl_linenode_line(x) (((intptr_t*)(x))[0]) +#define jl_linenode_file(x) (((jl_value_t**)(x))[1]) +#define jl_labelnode_label(x) (((intptr_t*)(x))[0]) +#define jl_slot_number(x) (((intptr_t*)(x))[0]) +#define jl_typedslot_get_type(x) (((jl_value_t**)(x))[1]) +#define jl_gotonode_label(x) (((intptr_t*)(x))[0]) +#define jl_globalref_mod(s) (*(jl_module_t**)(s)) +#define jl_globalref_name(s) (((jl_sym_t**)(s))[1]) #define jl_nparams(t) jl_svec_len(((jl_datatype_t*)(t))->parameters) #define jl_tparam0(t) jl_svecref(((jl_datatype_t*)(t))->parameters, 0) diff --git a/src/method.c b/src/method.c index 5a4f9f8100f92d..4cd52b82776e94 100644 --- a/src/method.c +++ b/src/method.c @@ -300,19 +300,27 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) jl_array_ptr_set(ex->args, 0, argnames); jl_fill_argnames((jl_array_t*)linfo->def->source, argnames); + // build the rest of the body to pass to expand jl_expr_t *scopeblock = jl_exprn(jl_symbol("scope-block"), 1); jl_array_ptr_set(ex->args, 1, scopeblock); - jl_expr_t *body = jl_exprn(jl_symbol("block"), 2); - jl_array_ptr_set(((jl_expr_t*)jl_exprarg(ex,1))->args, 0, body); + jl_expr_t *body = jl_exprn(jl_symbol("block"), 3); + jl_array_ptr_set(((jl_expr_t*)jl_exprarg(ex, 1))->args, 0, body); + + // add location meta linenum = jl_box_long(linfo->def->line); - jl_value_t *linenode = jl_new_struct(jl_linenumbernode_type, linenum); + jl_value_t *linenode = jl_new_struct(jl_linenumbernode_type, linenum, linfo->def->file); jl_array_ptr_set(body->args, 0, linenode); + jl_expr_t *pushloc = jl_exprn(meta_sym, 3); + jl_array_ptr_set(body->args, 1, pushloc); + jl_array_ptr_set(pushloc->args, 0, jl_symbol("push_loc")); + jl_array_ptr_set(pushloc->args, 1, linfo->def->file); // file + jl_array_ptr_set(pushloc->args, 2, jl_symbol("@generated body")); // function // invoke code generator assert(jl_nparams(tt) == jl_array_len(argnames) || (linfo->def->isva && (jl_nparams(tt) >= jl_array_len(argnames) - 1))); - jl_array_ptr_set(body->args, 1, - jl_call_staged(sparam_vals, generator, jl_svec_data(tt->parameters), jl_nparams(tt))); + jl_value_t *generated_body = jl_call_staged(sparam_vals, generator, jl_svec_data(tt->parameters), jl_nparams(tt)); + jl_array_ptr_set(body->args, 2, generated_body); if (linfo->def->sparam_syms != jl_emptysvec) { // mark this function as having the same static parameters as the generator @@ -335,8 +343,17 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) jl_array_t *stmts = (jl_array_t*)func->code; size_t i, l; for (i = 0, l = jl_array_len(stmts); i < l; i++) { - jl_array_ptr_set(stmts, i, jl_resolve_globals(jl_array_ptr_ref(stmts, i), linfo->def->module, env)); + jl_value_t *stmt = jl_array_ptr_ref(stmts, i); + stmt = jl_resolve_globals(stmt, linfo->def->module, env); + jl_array_ptr_set(stmts, i, stmt); } + + // add pop_loc meta + jl_array_ptr_1d_push(stmts, jl_nothing); + jl_expr_t *poploc = jl_exprn(meta_sym, 1); + jl_array_ptr_set(stmts, jl_array_len(stmts) - 1, poploc); + jl_array_ptr_set(poploc->args, 0, jl_symbol("pop_loc")); + ptls->in_pure_callback = last_in; jl_lineno = last_lineno; ptls->current_module = last_m; @@ -401,10 +418,27 @@ static void jl_method_set_source(jl_method_t *m, jl_code_info_t *src) int set_lineno = 0; for (i = 0; i < n; i++) { jl_value_t *st = jl_array_ptr_ref(stmts, i); - if (jl_is_expr(st) && ((jl_expr_t*)st)->head == line_sym) { + if (jl_is_linenode(st)) { if (!set_lineno) { - m->line = jl_unbox_long(jl_exprarg(st, 0)); - m->file = (jl_sym_t*)jl_exprarg(st, 1); + m->line = jl_linenode_line(st); + jl_value_t *file = jl_linenode_file(st); + if (jl_is_symbol(file)) + m->file = (jl_sym_t*)file; + st = jl_nothing; + set_lineno = 1; + } + } + else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == line_sym) { + if (!set_lineno) { + switch (jl_expr_nargs(st)) { + case 2: + m->file = (jl_sym_t*)jl_exprarg(st, 1); + JL_FALLTHROUGH; + case 1: + m->line = jl_unbox_long(jl_exprarg(st, 0)); + JL_FALLTHROUGH; + default: ; + } st = jl_nothing; set_lineno = 1; } diff --git a/src/rtutils.c b/src/rtutils.c index 9397cab1ec0a09..b04ad0228a28ff 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -757,7 +757,9 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt n += jl_printf(out, ">"); } else if (vt == jl_linenumbernode_type) { - n += jl_printf(out, "# line %" PRIuPTR, jl_linenode_line(v)); + n += jl_printf(out, "#= "); + n += jl_static_show_x(out, jl_linenode_file(v), depth); + n += jl_printf(out, ":%" PRIuPTR " =#", jl_linenode_line(v)); } else if (vt == jl_expr_type) { jl_expr_t *e = (jl_expr_t*)v; diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 32139c496a44f1..ceffcddca57eeb 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license # DO NOT ALTER ORDER OR SPACING OF METHODS BELOW -const lineoffset = @__LINE__ + 0 # XXX: __LINE__ at the end of a line is off-by-one +const lineoffset = @__LINE__ ambig(x, y) = 1 ambig(x::Integer, y) = 2 ambig(x, y::Integer) = 3 @@ -85,6 +85,16 @@ cfunction(ambig, Int, (UInt8, Int)) # test for a crash (doesn't throw an error) ambig(x, y::Integer) = 3 @test_throws MethodError ambig(2, 0x03) +# Method overwriting by an ambiguity should also invalidate the method cache (#21963) +ambig(x::Union{Char, Int8}) = 'r' +@test ambig('c') == 'r' +@test ambig(Int8(1)) == 'r' +@test_throws MethodError ambig(Int16(1)) +ambig(x::Union{Char, Int16}) = 's' +@test_throws MethodError ambig('c') +@test ambig(Int8(1)) == 'r' +@test ambig(Int16(1)) == 's' + # Automatic detection of ambiguities module Ambig1 ambig(x, y) = 1 diff --git a/test/arrayops.jl b/test/arrayops.jl index 8b5e6d559af9fd..56a06f325628aa 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -2082,12 +2082,12 @@ struct F21666{T <: Base.TypeArithmetic} x::Float32 end +Base.TypeArithmetic(::Type{F21666{T}}) where {T} = T() +Base.:+(x::F, y::F) where {F <: F21666} = F(x.x + y.x) +Base.convert(::Type{Float64}, x::F21666) = Float64(x.x) @testset "Exactness of cumsum # 21666" begin # test that cumsum uses more stable algorithm # for types with unknown/rounding arithmetic - Base.TypeArithmetic(::Type{F21666{T}}) where {T} = T - Base.:+(x::F, y::F) where {F <: F21666} = F(x.x + y.x) - Base.convert(::Type{Float64}, x::F21666) = Float64(x.x) # we make v pretty large, because stable algorithm may have a large base case v = zeros(300); v[1] = 2; v[200:end] = eps(Float32) @@ -2146,3 +2146,6 @@ end Base.:*(a::T11053, b::Real) = T11053(a.a*b) Base.:(==)(a::T11053, b::T11053) = a.a == b.a @test [T11053(1)] * 5 == [T11053(1)] .* 5 == [T11053(5.0)] + +#15907 +@test typeof(Array{Int,0}()) == Array{Int,0} diff --git a/test/ccall.jl b/test/ccall.jl index ad97132813279e..204a40c6080f35 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1265,3 +1265,15 @@ end (::CallableSingleton)(x, y) = x + y @test ccall(cfunction(CallableSingleton(), Int, Tuple{Int,Int}), Int, (Int, Int), 1, 2) === 3 + +# 19805 +mutable struct callinfos_19805{FUNC_FT<:Function} + f :: FUNC_FT +end + +evalf_callback_19805{FUNC_FT}(ci::callinfos_19805{FUNC_FT}) = ci.f(0.5)::Float64 + +evalf_callback_c_19805{FUNC_FT}(ci::callinfos_19805{FUNC_FT}) = cfunction( + evalf_callback_19805, Float64, (callinfos_19805{FUNC_FT},)) + +@test_throws ErrorException evalf_callback_c_19805( callinfos_19805(sin) ) diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index f5ca5f9698dd03..7278d6c214b41b 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -322,7 +322,7 @@ let exename = `$(Base.julia_cmd()) --precompiled=yes --startup-file=no` # issue #12671, starting from a non-directory # rm(dir) fails on windows with Permission denied # and was an upstream bug in llvm <= v3.3 - if !is_windows() && VersionNumber(Base.libllvm_version) > v"3.3" + if !is_windows() && Base.libllvm_version > v"3.3" testdir = mktempdir() cd(testdir) do rm(testdir) diff --git a/test/combinatorics.jl b/test/combinatorics.jl index 95fc8c5046ddde..c8fdeedf6df95a 100644 --- a/test/combinatorics.jl +++ b/test/combinatorics.jl @@ -67,4 +67,34 @@ end @test factorial(Int32(12)) === Int32(479001600) @test_throws OverflowError factorial(Int32(13)) end + + _fact_table64 = + Int64[1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800, + 87178291200,1307674368000,20922789888000,355687428096000,6402373705728000, + 121645100408832000,2432902008176640000] + + _fact_table128 = + UInt128[0x00000000000000000000000000000001, 0x00000000000000000000000000000002, + 0x00000000000000000000000000000006, 0x00000000000000000000000000000018, + 0x00000000000000000000000000000078, 0x000000000000000000000000000002d0, + 0x000000000000000000000000000013b0, 0x00000000000000000000000000009d80, + 0x00000000000000000000000000058980, 0x00000000000000000000000000375f00, + 0x00000000000000000000000002611500, 0x0000000000000000000000001c8cfc00, + 0x0000000000000000000000017328cc00, 0x0000000000000000000000144c3b2800, + 0x00000000000000000000013077775800, 0x00000000000000000000130777758000, + 0x00000000000000000001437eeecd8000, 0x00000000000000000016beecca730000, + 0x000000000000000001b02b9306890000, 0x000000000000000021c3677c82b40000, + 0x0000000000000002c5077d36b8c40000, 0x000000000000003ceea4c2b3e0d80000, + 0x000000000000057970cd7e2933680000, 0x00000000000083629343d3dcd1c00000, + 0x00000000000cd4a0619fb0907bc00000, 0x00000000014d9849ea37eeac91800000, + 0x00000000232f0fcbb3e62c3358800000, 0x00000003d925ba47ad2cd59dae000000, + 0x0000006f99461a1e9e1432dcb6000000, 0x00000d13f6370f96865df5dd54000000, + 0x0001956ad0aae33a4560c5cd2c000000, 0x0032ad5a155c6748ac18b9a580000000, + 0x0688589cc0e9505e2f2fee5580000000, 0xde1bc4d19efcac82445da75b00000000] + + for expected in Any[_fact_table64, _fact_table128] + for (n, factn) in enumerate(expected) + @test factorial(oftype(factn, n)) === factn + end + end end diff --git a/test/complex.jl b/test/complex.jl index 3aa4dd02d25b75..161222835a6869 100644 --- a/test/complex.jl +++ b/test/complex.jl @@ -883,6 +883,7 @@ end @test exp2(1.0+0.0im) == 2.0+0.0im #wolframalpha @test exp2(1.0+3.0im) ≈ -0.9739888359315627962096198412+1.74681016354974281701922im + @test exp2(im) ≈ 0.7692389013639721 + 0.6389612763136348im end @testset "exp10" begin @@ -890,6 +891,7 @@ end @test exp10(1.0+0.0im) == 10.0+0.0im #wolframalpha @test exp10(1.0+2.0im) ≈ -1.0701348355877020772086517528518239460495529361-9.9425756941378968736161937190915602112878340717im + @test exp10(im) ≈ -0.6682015101903132 + 0.7439803369574931im end @testset "round and float, PR #8291" begin @@ -946,9 +948,12 @@ end @testset "Complex Irrationals, issue #21204" begin for x in (pi, e, catalan) # No need to test all of them - @test typeof(Complex(x, x)) == Complex{typeof(x)} - @test exp(complex(x, x)) ≈ exp(x) * cis(x) - @test log1p(complex(x, x)) ≈ log(1 + complex(x, x)) + z = Complex(x, x) + @test typeof(z) == Complex{typeof(x)} + @test exp(z) ≈ exp(x) * cis(x) + @test log1p(z) ≈ log(1 + z) + @test exp2(z) ≈ exp(z * log(2)) + @test exp10(z) ≈ exp(z * log(10)) end end diff --git a/test/core.jl b/test/core.jl index b58b3c1169e3e8..37afe6c68fb26a 100644 --- a/test/core.jl +++ b/test/core.jl @@ -438,16 +438,27 @@ glotest() @test loc_x == 10 # issue #7234 +f7234_cnt = 0 begin glob_x2 = 24 - f7234_a() = (glob_x2 += 1) + function f7234_a() + global f7234_cnt += 1 + glob_x2 += 1 + global f7234_cnt += -10000 + end end @test_throws UndefVarError f7234_a() +@test f7234_cnt == 1 begin global glob_x2 = 24 - f7234_b() = (glob_x2 += 1) + function f7234_b() + global f7234_cnt += 1 + glob_x2 += 1 + global f7235_cnt += -10000 + end end @test_throws UndefVarError f7234_b() +@test f7234_cnt == 2 # existing globals can be inherited by non-function blocks for i = 1:2 glob_x2 += 1 @@ -486,16 +497,23 @@ end @test h19333() == 4 # let - new variables, including undefinedness +let_undef_cnt = 0 function let_undef() first = true for i = 1:2 - let x - if first; x=1; first=false; end - x+1 + let x # new x + if first # not defined on second pass + x = 1 + first = false + end + global let_undef_cnt += 1 + x + 1 + global let_undef_cnt += 23 end end end @test_throws UndefVarError let_undef() +@test let_undef_cnt == 25 # const implies local in a local scope block function const_implies_local() @@ -521,6 +539,56 @@ end @test a[2](10) == 12 @test a[3](10) == 13 +# issue #21900 +f21900_cnt = 0 +function f21900() + for i = 1:1 + x = 0 + end + global f21900_cnt += 1 + x + global f21900_cnt += -1000 + nothing +end +@test_throws UndefVarError f21900() +@test f21900_cnt == 1 + +@test_throws UndefVarError @eval begin + for i21900 = 1:10 + for j21900 = 1:10 + foo21900 = 10 + end + bar21900 = 0 + bar21900 = foo21900 + 1 + end +end +@test !isdefined(:foo21900) +@test !isdefined(:bar21900) +bar21900 = 0 +@test_throws UndefVarError @eval begin + for i21900 = 1:10 + for j21900 = 1:10 + foo21900 = 10 + end + bar21900 = -1 + bar21900 = foo21900 + 1 + end +end +@test bar21900 == -1 +@test !isdefined(:foo21900) +foo21900 = 0 +@test nothing === @eval begin + for i21900 = 1:10 + for j21900 = 1:10 + foo21900 = 10 + end + bar21900 = -1 + bar21900 = foo21900 + 1 + end +end +@test foo21900 == 10 +@test bar21900 == 11 + # ? syntax @test (true ? 1 : false ? 2 : 3) == 1 diff --git a/test/docs.jl b/test/docs.jl index 46b1523e564013..eadd59e65cad16 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -34,6 +34,20 @@ macro macro_doctest() end @test (@doc @macro_doctest) !== nothing +# test that random stuff interpolated into docstrings doesn't break search or other methods here +doc""" +break me: + + code + +$:asymbol # a symbol +$1 # a number +$string # a function +$$latex literal$$ +### header! +""" +function break_me_docs end + # issue #11548 module ModuleMacroDoc @@ -48,7 +62,7 @@ end # General tests for docstrings. -const LINE_NUMBER = @__LINE__+1 +const LINE_NUMBER = @__LINE__() + 1 "DocsTest" module DocsTest @@ -481,24 +495,26 @@ end # Issue #16359. Error message for invalid doc syntax. -for each in [ # valid syntax - :(f()), - :(f(x)), - :(f(x::Int)), - :(f(x...)), - :(f(x = 1)), - :(f(; x = 1)) - ] - @test Meta.isexpr(Docs.docm("...", each), :block) -end -for each in [ # invalid syntax - :(f("...")), - :(f(1, 2)), - :(f(() -> ())) - ] - result = Docs.docm("...", each) - @test Meta.isexpr(result, :call) - @test result.args[1] === error +let __source__ = LineNumberNode(0) + for each in [ # valid syntax + :(f()), + :(f(x)), + :(f(x::Int)), + :(f(x...)), + :(f(x = 1)), + :(f(; x = 1)) + ] + @test Meta.isexpr(Docs.docm(__source__, "...", each), :block) + end + for each in [ # invalid syntax + :(f("...")), + :(f(1, 2)), + :(f(() -> ())) + ] + result = Docs.docm(__source__, "...", each) + @test Meta.isexpr(result, :call) + @test result.args[1] === error + end end # Issue #15424. Non-markdown docstrings. @@ -906,23 +922,24 @@ let x = Binding(Main, :⊕) @test parse(string(x)) == :(⊕) end +doc_util_path = Symbol(joinpath("docs", "utils.jl")) # Docs.helpmode tests: we test whether the correct expressions are being generated here, # rather than complete integration with Julia's REPL mode system. for (line, expr) in Pair[ "sin" => :sin, "Base.sin" => :(Base.sin), - "@time(x)" => :(@time(x)), - "@time" => :(:@time), - ":@time" => :(:@time), - "@time()" => :(@time), - "Base.@time()" => :(Base.@time), + "@time(x)" => Expr(:macrocall, Symbol("@time"), LineNumberNode(1, :none), :x), + "@time" => Expr(:macrocall, Symbol("@time"), LineNumberNode(1, :none)), + ":@time" => Expr(:quote, (Expr(:macrocall, Symbol("@time"), LineNumberNode(1, :none)))), + "@time()" => Expr(:macrocall, Symbol("@time"), LineNumberNode(1, :none)), + "Base.@time()" => Expr(:macrocall, Expr(:., :Base, QuoteNode(Symbol("@time"))), LineNumberNode(1, :none)), "ccall" => :ccall, # keyword "while " => :while, # keyword, trailing spaces should be stripped. "0" => 0, "\"...\"" => "...", - "r\"...\"" => :(r"..."), + "r\"...\"" => Expr(:macrocall, Symbol("@r_str"), LineNumberNode(1, :none), "...") ] - @test Docs.helpmode(line) == :(Base.Docs.@repl($STDOUT, $expr)) + @test Docs.helpmode(line) == Expr(:macrocall, Expr(:., Expr(:., :Base, QuoteNode(:Docs)), QuoteNode(Symbol("@repl"))), LineNumberNode(117, doc_util_path), STDOUT, expr) buf = IOBuffer() @test eval(Base, Docs.helpmode(buf, line)) isa Union{Base.Markdown.MD,Void} end @@ -961,8 +978,8 @@ dynamic_test.x = "test 2" @test @doc(dynamic_test) == "test 2 Union{}" @test @doc(dynamic_test(::String)) == "test 2 Tuple{String}" -@test Docs._repl(:(dynamic_test(1.0))) == :(@doc $(Expr(:escape, :(dynamic_test(::typeof(1.0)))))) -@test Docs._repl(:(dynamic_test(::String))) == :(@doc $(Expr(:escape, :(dynamic_test(::String))))) +@test Docs._repl(:(dynamic_test(1.0))) == Expr(:macrocall, Symbol("@doc"), LineNumberNode(204, doc_util_path), esc(:(dynamic_test(::typeof(1.0))))) +@test Docs._repl(:(dynamic_test(::String))) == Expr(:macrocall, Symbol("@doc"), LineNumberNode(204, doc_util_path), esc(:(dynamic_test(::String)))) # Equality testing @@ -1011,3 +1028,21 @@ end """ ) +# issue #22105 +module I22105 + lineno = @__LINE__ + """foo docs""" + function foo end +end + +let foo_docs = meta(I22105)[@var(I22105.foo)].docs + @test length(foo_docs) === 1 + @test isa(first(foo_docs), Pair) + local docstr = first(foo_docs).second + @test isa(docstr, DocStr) + @test docstr.data[:path] == Base.source_path() + @test docstr.data[:linenumber] == I22105.lineno + 1 + @test docstr.data[:module] === I22105 + @test docstr.data[:typesig] === Union{} + @test docstr.data[:binding] == Binding(I22105, :foo) +end diff --git a/test/inference.jl b/test/inference.jl index c8cd2969598a83..61d283c73368c3 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -778,6 +778,37 @@ function break_21369() end @test_throws ErrorException break_21369() # not TypeError +# issue #17003 +abstract type AArray_17003{T,N} end +AVector_17003{T} = AArray_17003{T,1} + +struct Nable_17003{T} +end + +struct NArray_17003{T,N} <: AArray_17003{Nable_17003{T},N} +end + +(::Type{NArray_17003}){T,N}(::Array{T,N}) = NArray_17003{T,N}() + +gl_17003 = [1, 2, 3] + +f2_17003(item::AVector_17003) = nothing +f2_17003(::Any) = f2_17003(NArray_17003(gl_17003)) + +@test f2_17003(1) == nothing + +# issue #20847 +function segfaultfunction_20847{N, T}(A::Vector{NTuple{N, T}}) + B = reinterpret(T, A, (N, length(A))) + return nothing +end + +tuplevec_20847 = Tuple{Float64, Float64}[(0.0,0.0), (1.0,0.0)] + +for A in (1,) + @test segfaultfunction_20847(tuplevec_20847) == nothing +end + # issue #21848 @test Core.Inference.limit_type_depth(Ref{Complex{T} where T}, Core.Inference.MAX_TYPE_DEPTH) == Ref let T = Tuple{Tuple{Int64, Void}, @@ -788,3 +819,27 @@ let T = Tuple{Tuple{Int64, Void}, @test Core.Inference.limit_type_depth(T, 1) >: T @test Core.Inference.limit_type_depth(T, 2) >: T end + +# Issue #20902, check that this doesn't error. +@generated function test_20902() + quote + 10 + 11 + end +end +@test length(code_typed(test_20902, (), optimize = false)) == 1 +@test length(code_typed(test_20902, (), optimize = false)) == 1 + +# normalization of arguments with constant Types as parameters +g21771(T) = T +f21771(::Val{U}) where {U} = Tuple{g21771(U)} +@test @inferred(f21771(Val{Int}())) === Tuple{Int} +@test @inferred(f21771(Val{Union{}}())) === Tuple{Union{}} +@test @inferred(f21771(Val{Integer}())) === Tuple{Integer} + +# missing method should be inferred as Union{}, ref https://github.com/JuliaLang/julia/issues/20033#issuecomment-282228948 +@test Base.return_types(f -> f(1), (typeof((x::String) -> x),)) == Any[Union{}] + +# issue #21653 +# ensure that we don't try to resolve cycles using uncached edges +f21653() = f21653() +@test code_typed(f21653, Tuple{}, optimize=false)[1] isa Pair{CodeInfo, typeof(Union{})} diff --git a/test/libgit2.jl b/test/libgit2.jl index f179825ae3fda7..18d0137a63555a 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -1628,6 +1628,7 @@ mktempdir() do dir loopback = ip"127.0.0.1" for hostname in hostnames + local addr try addr = getaddrinfo(hostname) catch diff --git a/test/linalg/cholesky.jl b/test/linalg/cholesky.jl index e6aabd7f8ff179..0364b4bfb9fa27 100644 --- a/test/linalg/cholesky.jl +++ b/test/linalg/cholesky.jl @@ -1,165 +1,157 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -debug = false - using Base.Test -using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted +using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted, PosDefException -n = 10 +@testset "core functionality" begin + n = 10 -# Split n into 2 parts for tests needing two matrices -n1 = div(n, 2) -n2 = 2*n1 + # Split n into 2 parts for tests needing two matrices + n1 = div(n, 2) + n2 = 2*n1 -srand(1234321) + srand(1234321) -areal = randn(n,n)/2 -aimg = randn(n,n)/2 -a2real = randn(n,n)/2 -a2img = randn(n,n)/2 -breal = randn(n,2)/2 -bimg = randn(n,2)/2 + areal = randn(n,n)/2 + aimg = randn(n,n)/2 + a2real = randn(n,n)/2 + a2img = randn(n,n)/2 + breal = randn(n,2)/2 + bimg = randn(n,2)/2 -for eltya in (Float32, Float64, Complex64, Complex128, BigFloat, Int) - a = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(areal, aimg) : areal) - a2 = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(a2real, a2img) : a2real) - apd = a'*a # symmetric positive-definite + for eltya in (Float32, Float64, Complex64, Complex128, BigFloat, Int) + a = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(areal, aimg) : areal) + a2 = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(a2real, a2img) : a2real) + apd = a'*a # symmetric positive-definite - apds = Symmetric(apd) - apdsL = Symmetric(apd, :L) - apdh = Hermitian(apd) - apdhL = Hermitian(apd, :L) - ε = εa = eps(abs(float(one(eltya)))) + apds = Symmetric(apd) + apdsL = Symmetric(apd, :L) + apdh = Hermitian(apd) + apdhL = Hermitian(apd, :L) + ε = εa = eps(abs(float(one(eltya)))) - @inferred cholfact(apd) - @inferred chol(apd) - capd = factorize(apd) - r = capd[:U] - κ = cond(apd, 1) #condition number + @inferred cholfact(apd) + @inferred chol(apd) + capd = factorize(apd) + r = capd[:U] + κ = cond(apd, 1) #condition number - #getindex - @test_throws KeyError capd[:Z] + #getindex + @test_throws KeyError capd[:Z] - #Test error bound on reconstruction of matrix: LAWNS 14, Lemma 2.1 + #Test error bound on reconstruction of matrix: LAWNS 14, Lemma 2.1 - #these tests were failing on 64-bit linux when inside the inner loop - #for eltya = Complex64 and eltyb = Int. The E[i,j] had NaN32 elements - #but only with srand(1234321) set before the loops. - E = abs.(apd - r'*r) - for i=1:n, j=1:n - @test E[i,j] <= (n+1)ε/(1-(n+1)ε)*real(sqrt(apd[i,i]*apd[j,j])) - end - E = abs.(apd - full(capd)) - for i=1:n, j=1:n - @test E[i,j] <= (n+1)ε/(1-(n+1)ε)*real(sqrt(apd[i,i]*apd[j,j])) - end - @test apd*inv(capd) ≈ eye(n) - @test abs((det(capd) - det(apd))/det(capd)) <= ε*κ*n # Ad hoc, but statistically verified, revisit - @test @inferred(logdet(capd)) ≈ log(det(capd)) # logdet is less likely to overflow - - apos = apd[1,1] # test chol(x::Number), needs x>0 - @test all(x -> x ≈ √apos, cholfact(apos).factors) - @test_throws ArgumentError chol(-one(eltya)) - - if eltya <: Real - capds = cholfact(apds) - @test inv(capds)*apds ≈ eye(n) - @test abs((det(capds) - det(apd))/det(capds)) <= ε*κ*n - if eltya <: BlasReal - capds = cholfact!(copy(apds)) + #these tests were failing on 64-bit linux when inside the inner loop + #for eltya = Complex64 and eltyb = Int. The E[i,j] had NaN32 elements + #but only with srand(1234321) set before the loops. + E = abs.(apd - r'*r) + for i=1:n, j=1:n + @test E[i,j] <= (n+1)ε/(1-(n+1)ε)*real(sqrt(apd[i,i]*apd[j,j])) + end + E = abs.(apd - full(capd)) + for i=1:n, j=1:n + @test E[i,j] <= (n+1)ε/(1-(n+1)ε)*real(sqrt(apd[i,i]*apd[j,j])) + end + @test apd*inv(capd) ≈ eye(n) + @test abs((det(capd) - det(apd))/det(capd)) <= ε*κ*n # Ad hoc, but statistically verified, revisit + @test @inferred(logdet(capd)) ≈ log(det(capd)) # logdet is less likely to overflow + + apos = apd[1,1] # test chol(x::Number), needs x>0 + @test all(x -> x ≈ √apos, cholfact(apos).factors) + @test_throws PosDefException chol(-one(eltya)) + + if eltya <: Real + capds = cholfact(apds) @test inv(capds)*apds ≈ eye(n) @test abs((det(capds) - det(apd))/det(capds)) <= ε*κ*n + if eltya <: BlasReal + capds = cholfact!(copy(apds)) + @test inv(capds)*apds ≈ eye(n) + @test abs((det(capds) - det(apd))/det(capds)) <= ε*κ*n + end + ulstring = sprint(show,capds[:UL]) + @test sprint(show,capds) == "$(typeof(capds)) with factor:\n$ulstring" + else + capdh = cholfact(apdh) + @test inv(capdh)*apdh ≈ eye(n) + @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n + capdh = cholfact!(copy(apdh)) + @test inv(capdh)*apdh ≈ eye(n) + @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n + capdh = cholfact!(copy(apd)) + @test inv(capdh)*apdh ≈ eye(n) + @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n + capdh = cholfact!(copy(apd), :L) + @test inv(capdh)*apdh ≈ eye(n) + @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n + ulstring = sprint(show,capdh[:UL]) + @test sprint(show,capdh) == "$(typeof(capdh)) with factor:\n$ulstring" end - ulstring = sprint(show,capds[:UL]) - @test sprint(show,capds) == "$(typeof(capds)) with factor:\n$ulstring" - else - capdh = cholfact(apdh) - @test inv(capdh)*apdh ≈ eye(n) - @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n - capdh = cholfact!(copy(apdh)) - @test inv(capdh)*apdh ≈ eye(n) - @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n - capdh = cholfact!(copy(apd)) - @test inv(capdh)*apdh ≈ eye(n) - @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n - capdh = cholfact!(copy(apd), :L) - @test inv(capdh)*apdh ≈ eye(n) - @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n - ulstring = sprint(show,capdh[:UL]) - @test sprint(show,capdh) == "$(typeof(capdh)) with factor:\n$ulstring" - end - # test chol of 2x2 Strang matrix - S = convert(AbstractMatrix{eltya},full(SymTridiagonal([2,2],[-1]))) - U = Bidiagonal([2,sqrt(eltya(3))],[-1],true) / sqrt(eltya(2)) - @test full(chol(S)) ≈ full(U) - - #lower Cholesky factor - lapd = cholfact(apd, :L) - @test full(lapd) ≈ apd - l = lapd[:L] - @test l*l' ≈ apd - @test triu(capd.factors) ≈ lapd[:U] - @test tril(lapd.factors) ≈ capd[:L] - if eltya <: Real - capds = cholfact(apds) - lapds = cholfact(apdsL) - cl = chol(apdsL) - ls = lapds[:L] - @test ls*ls' ≈ apd - @test triu(capds.factors) ≈ lapds[:U] - @test tril(lapds.factors) ≈ capds[:L] - @test istriu(cl) - @test cl'cl ≈ apds - @test cl'cl ≈ apdsL - else - capdh = cholfact(apdh) - lapdh = cholfact(apdhL) - cl = chol(apdhL) - ls = lapdh[:L] - @test ls*ls' ≈ apd - @test triu(capdh.factors) ≈ lapdh[:U] - @test tril(lapdh.factors) ≈ capdh[:L] - @test istriu(cl) - @test cl'cl ≈ apdh - @test cl'cl ≈ apdhL - end + # test chol of 2x2 Strang matrix + S = convert(AbstractMatrix{eltya},full(SymTridiagonal([2,2],[-1]))) + U = Bidiagonal([2,sqrt(eltya(3))],[-1],true) / sqrt(eltya(2)) + @test full(chol(S)) ≈ full(U) + + #lower Cholesky factor + lapd = cholfact(apd, :L) + @test full(lapd) ≈ apd + l = lapd[:L] + @test l*l' ≈ apd + @test triu(capd.factors) ≈ lapd[:U] + @test tril(lapd.factors) ≈ capd[:L] + if eltya <: Real + capds = cholfact(apds) + lapds = cholfact(apdsL) + cl = chol(apdsL) + ls = lapds[:L] + @test ls*ls' ≈ apd + @test triu(capds.factors) ≈ lapds[:U] + @test tril(lapds.factors) ≈ capds[:L] + @test istriu(cl) + @test cl'cl ≈ apds + @test cl'cl ≈ apdsL + else + capdh = cholfact(apdh) + lapdh = cholfact(apdhL) + cl = chol(apdhL) + ls = lapdh[:L] + @test ls*ls' ≈ apd + @test triu(capdh.factors) ≈ lapdh[:U] + @test tril(lapdh.factors) ≈ capdh[:L] + @test istriu(cl) + @test cl'cl ≈ apdh + @test cl'cl ≈ apdhL + end - #pivoted upper Cholesky - if eltya != BigFloat - cz = cholfact(zeros(eltya,n,n), :U, Val{true}) - @test_throws Base.LinAlg.RankDeficientException Base.LinAlg.chkfullrank(cz) - cpapd = cholfact(apd, :U, Val{true}) - @test rank(cpapd) == n - @test all(diff(diag(real(cpapd.factors))).<=0.) # diagonal should be non-increasing - if isreal(apd) - @test apd*inv(cpapd) ≈ eye(n) + #pivoted upper Cholesky + if eltya != BigFloat + cz = cholfact(zeros(eltya,n,n), :U, Val{true}) + @test_throws Base.LinAlg.RankDeficientException Base.LinAlg.chkfullrank(cz) + cpapd = cholfact(apd, :U, Val{true}) + @test rank(cpapd) == n + @test all(diff(diag(real(cpapd.factors))).<=0.) # diagonal should be non-increasing + if isreal(apd) + @test apd*inv(cpapd) ≈ eye(n) + end + @test full(cpapd) ≈ apd + #getindex + @test_throws KeyError cpapd[:Z] + + @test size(cpapd) == size(apd) + @test full(copy(cpapd)) ≈ apd + @test det(cpapd) ≈ det(apd) + @test logdet(cpapd) ≈ logdet(apd) + @test cpapd[:P]*cpapd[:L]*cpapd[:U]*cpapd[:P]' ≈ apd end - @test full(cpapd) ≈ apd - #getindex - @test_throws KeyError cpapd[:Z] - @test size(cpapd) == size(apd) - @test full(copy(cpapd)) ≈ apd - @test det(cpapd) ≈ det(apd) - @test logdet(cpapd) ≈ logdet(apd) - @test cpapd[:P]*cpapd[:L]*cpapd[:U]*cpapd[:P]' ≈ apd - end + for eltyb in (Float32, Float64, Complex64, Complex128, Int) + b = eltyb == Int ? rand(1:5, n, 2) : convert(Matrix{eltyb}, eltyb <: Complex ? complex.(breal, bimg) : breal) + εb = eps(abs(float(one(eltyb)))) + ε = max(εa,εb) - for eltyb in (Float32, Float64, Complex64, Complex128, Int) - b = eltyb == Int ? rand(1:5, n, 2) : convert(Matrix{eltyb}, eltyb <: Complex ? complex.(breal, bimg) : breal) - εb = eps(abs(float(one(eltyb)))) - ε = max(εa,εb) - -debug && println("\ntype of a: ", eltya, " type of b: ", eltyb, "\n") - let Bs = b - for atype in ("Array", "SubArray") - if atype == "Array" - b = Bs - else - b = view(Bs, 1:n, 1) - end + for b in (b, view(b, 1:n, 1)) # Array and SubArray # Test error bound on linear solver: LAWNS 14, Theorem 2.1 # This is a surprisingly loose bound @@ -175,7 +167,6 @@ debug && println("\ntype of a: ", eltya, " type of b: ", eltyb, "\n") end @test_throws DimensionMismatch lapd\RowVector(ones(n)) -debug && println("pivoted Cholesky decomposition") if eltya != BigFloat && eltyb != BigFloat # Note! Need to implement pivoted Cholesky decomposition in julia @test norm(apd * (cpapd\b) - b)/norm(b) <= ε*κ*n # Ad hoc, revisit @@ -192,12 +183,10 @@ debug && println("pivoted Cholesky decomposition") end end -begin - # Cholesky factor of Matrix with non-commutative elements, here 2x2-matrices - +@testset "Cholesky factor of Matrix with non-commutative elements, here 2x2-matrices" begin X = Matrix{Float64}[0.1*rand(2,2) for i in 1:3, j = 1:3] - L = full(Base.LinAlg._chol!(X*X', LowerTriangular)) - U = full(Base.LinAlg._chol!(X*X', UpperTriangular)) + L = full(Base.LinAlg._chol!(X*X', LowerTriangular)[1]) + U = full(Base.LinAlg._chol!(X*X', UpperTriangular)[1]) XX = full(X*X') @test sum(sum(norm, L*L' - XX)) < eps() @@ -205,19 +194,22 @@ begin end # Test generic cholfact! -for elty in (Float32, Float64, Complex{Float32}, Complex{Float64}) - if elty <: Complex - A = complex.(randn(5,5), randn(5,5)) - else - A = randn(5,5) +@testset "generic cholfact!" begin + for elty in (Float32, Float64, Complex{Float32}, Complex{Float64}) + if elty <: Complex + A = complex.(randn(5,5), randn(5,5)) + else + A = randn(5,5) + end + A = convert(Matrix{elty}, A'A) + @test full(cholfact(A)[:L]) ≈ full(invoke(Base.LinAlg._chol!, Tuple{AbstractMatrix, Type{LowerTriangular}}, copy(A), LowerTriangular)[1]) + @test full(cholfact(A)[:U]) ≈ full(invoke(Base.LinAlg._chol!, Tuple{AbstractMatrix, Type{UpperTriangular}}, copy(A), UpperTriangular)[1]) end - A = convert(Matrix{elty}, A'A) - @test full(cholfact(A)[:L]) ≈ full(invoke(Base.LinAlg._chol!, Tuple{AbstractMatrix, Type{LowerTriangular}}, copy(A), LowerTriangular)) - @test full(cholfact(A)[:U]) ≈ full(invoke(Base.LinAlg._chol!, Tuple{AbstractMatrix, Type{UpperTriangular}}, copy(A), UpperTriangular)) end -# Test up- and downdates -let A = complex.(randn(10,5), randn(10, 5)), v = complex.(randn(5), randn(5)) +@testset "cholesky up- and downdates" begin + A = complex.(randn(10,5), randn(10, 5)) + v = complex.(randn(5), randn(5)) for uplo in (:U, :L) AcA = A'A BcB = AcA + v*v' @@ -231,8 +223,8 @@ let A = complex.(randn(10,5), randn(10, 5)), v = complex.(randn(5), randn(5)) end end -# issue #13243, unexpected nans in complex cholfact -let apd = [5.8525753f0 + 0.0f0im -0.79540455f0 + 0.7066077f0im 0.98274714f0 + 1.3824869f0im 2.619998f0 + 1.8532984f0im -1.8306153f0 - 1.2336911f0im 0.32275113f0 + 0.015575029f0im 2.1968813f0 + 1.0640624f0im 0.27894387f0 + 0.97911835f0im 3.0476584f0 + 0.18548489f0im 0.3842994f0 + 0.7050991f0im +@testset "issue #13243, unexpected nans in complex cholfact" begin + apd = [5.8525753f0 + 0.0f0im -0.79540455f0 + 0.7066077f0im 0.98274714f0 + 1.3824869f0im 2.619998f0 + 1.8532984f0im -1.8306153f0 - 1.2336911f0im 0.32275113f0 + 0.015575029f0im 2.1968813f0 + 1.0640624f0im 0.27894387f0 + 0.97911835f0im 3.0476584f0 + 0.18548489f0im 0.3842994f0 + 0.7050991f0im -0.79540455f0 - 0.7066077f0im 8.313246f0 + 0.0f0im -1.8076122f0 - 0.8882447f0im 0.47806996f0 + 0.48494184f0im 0.5096429f0 - 0.5395974f0im -0.7285097f0 - 0.10360408f0im -1.1760061f0 - 2.7146957f0im -0.4271084f0 + 0.042899966f0im -1.7228563f0 + 2.8335886f0im 1.8942566f0 + 0.6389735f0im 0.98274714f0 - 1.3824869f0im -1.8076122f0 + 0.8882447f0im 9.367975f0 + 0.0f0im -0.1838578f0 + 0.6468568f0im -1.8338387f0 + 0.7064959f0im 0.041852742f0 - 0.6556877f0im 2.5673025f0 + 1.9732997f0im -1.1148382f0 - 0.15693812f0im 2.4704504f0 - 1.0389464f0im 1.0858271f0 - 1.298006f0im 2.619998f0 - 1.8532984f0im 0.47806996f0 - 0.48494184f0im -0.1838578f0 - 0.6468568f0im 3.1117508f0 + 0.0f0im -1.956626f0 + 0.22825956f0im 0.07081801f0 - 0.31801307f0im 0.3698375f0 - 0.5400855f0im 0.80686307f0 + 1.5315914f0im 1.5649154f0 - 1.6229297f0im -0.112077385f0 + 1.2014246f0im @@ -262,13 +254,25 @@ let apd = [5.8525753f0 + 0.0f0im -0.79540455f0 + 0.7066077f0im 0.98274714f0 + 1. end end -# Fail if non-Hermitian -@test_throws ArgumentError cholfact(randn(5,5)) -@test_throws ArgumentError cholfact(complex.(randn(5,5), randn(5,5))) -@test_throws ArgumentError Base.LinAlg.chol!(randn(5,5)) -@test_throws ArgumentError Base.LinAlg.cholfact!(randn(5,5),:U,Val{false}) -@test_throws ArgumentError Base.LinAlg.cholfact!(randn(5,5),:U,Val{true}) -@test_throws ArgumentError cholfact(randn(5,5),:U,Val{false}) +@testset "throw if non-Hermitian" begin + @test_throws ArgumentError cholfact(randn(5,5)) + @test_throws ArgumentError cholfact(complex.(randn(5,5), randn(5,5))) + @test_throws ArgumentError Base.LinAlg.chol!(randn(5,5)) + @test_throws ArgumentError Base.LinAlg.cholfact!(randn(5,5),:U,Val{false}) + @test_throws ArgumentError Base.LinAlg.cholfact!(randn(5,5),:U,Val{true}) + @test_throws ArgumentError cholfact(randn(5,5),:U,Val{false}) +end -# Fail for non-BLAS element types -@test_throws ArgumentError cholfact!(Hermitian(rand(Float16, 5,5)), Val{true}) +@testset "fail for non-BLAS element types" begin + @test_throws ArgumentError cholfact!(Hermitian(rand(Float16, 5,5)), Val{true}) +end + +@testset "throw for non positive definite matrix" begin + for T in (Float32, Float64, Complex64, Complex128) + A = T[1 2; 2 1]; B = T[1, 1] + C = cholfact(A) + @test_throws PosDefException C\B + @test_throws PosDefException det(C) + @test_throws PosDefException logdet(C) + end +end diff --git a/test/llvmcall.jl b/test/llvmcall.jl index ac75a3575ac294..fc59bd025939f7 100644 --- a/test/llvmcall.jl +++ b/test/llvmcall.jl @@ -177,7 +177,7 @@ module ObjLoadTest end # Test for proper parenting -if VersionNumber(Base.libllvm_version) >= v"3.6" # llvm 3.6 changed the syntax for a gep, so just ignore this test on older versions +if Base.libllvm_version >= v"3.6" # llvm 3.6 changed the syntax for a gep, so just ignore this test on older versions local foo function foo() # this IR snippet triggers an optimization relying diff --git a/test/loading.jl b/test/loading.jl index 80f14a8ba08dbb..a39e0940618599 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -2,22 +2,51 @@ using Base.Test -@test @__LINE__ == 5 +# Tests for @__LINE__ inside and outside of macros +@test (@__LINE__) == 6 + +macro macro_caller_lineno() + @test 9 == (@__LINE__) != __source__.line > 12 + return __source__.line +end + +@test @macro_caller_lineno() == (@__LINE__) > 12 + +# @__LINE__ in a macro expands to the location of the macrocall in the source +# while __source__.line is the location of the macro caller +macro nested_LINE_expansion() + return quote + return (@emit_LINE, $(__source__.line)) + end +end +macro nested_LINE_expansion2() + return :((@emit_LINE, $(__source__.line))) +end +macro emit_LINE() + return quote + (@__LINE__, $(__source__.line)) + end +end +@test (@emit_LINE) == ((@__LINE__) - 3, @__LINE__) +@test @nested_LINE_expansion() == ((@__LINE__() - 4, @__LINE__() - 12), @__LINE__()) +@test @nested_LINE_expansion2() == ((@__LINE__() - 5, @__LINE__() - 9), @__LINE__()) include("test_sourcepath.jl") thefname = "the fname!//\\&\1*" include_string_test_func = include_string("include_string_test() = @__FILE__", thefname) -@test include_string_test_func() == Base.source_path() +@test include_string_test_func() == thefname @test include_string("Base.source_path()", thefname) == Base.source_path() @test basename(@__FILE__) == "loading.jl" @test isabspath(@__FILE__) @test isdir(@__DIR__) @test @__DIR__() == dirname(@__FILE__) -let exename = `$(Base.julia_cmd()) --precompiled=yes --startup-file=no` - wd = sprint(show, pwd()) +let exename = `$(Base.julia_cmd()) --precompiled=yes --startup-file=no`, + wd = sprint(show, abspath(pwd(), "")), + s_dir = sprint(show, joinpath(realpath(tempdir()), "")) + @test wd != s_dir @test readchomp(`$exename -E "@__DIR__" -i`) == wd - @test readchomp(`$exename -E "cd(()->eval(:(@__DIR__)), tempdir())" -i`) != wd + @test readchomp(`$exename -E "cd(()->eval(:(@__DIR__)), $s_dir)" -i`) == s_dir @test readchomp(`$exename -E "@__DIR__"`) == wd # non-interactive end diff --git a/test/osutils.jl b/test/osutils.jl index 270680c54b601b..b84688f55609b3 100644 --- a/test/osutils.jl +++ b/test/osutils.jl @@ -13,9 +13,9 @@ @test Base.is_unix(:FreeBSD) @test_throws ArgumentError Base.is_unix(:BeOS) if !is_windows() - @test Sys.windows_version() === (0, 0) + @test Sys.windows_version() == v"0.0.0" else - @test (Sys.windows_version()::Tuple{Int,Int})[1] > 0 + @test Sys.windows_version() >= v"1.0.0-" end @test (@static true ? 1 : 2) === 1 diff --git a/test/parse.jl b/test/parse.jl index 2b607b9256f9c0..9711b0fd0e203d 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -147,10 +147,10 @@ macro test999_str(args...); args; end # issue 11970 @test parseall(""" -macro f(args...) end; @f "" + macro f(args...) end; @f "macro argument" """) == Expr(:toplevel, - Expr(:macro, Expr(:call, :f, Expr(:..., :args)), Expr(:block, Expr(:line, 1, :none))), - Expr(:macrocall, Symbol("@f"), "")) + Expr(:macro, Expr(:call, :f, Expr(:..., :args)), Expr(:block, LineNumberNode(1, :none))), + Expr(:macrocall, Symbol("@f"), LineNumberNode(1, :none), "macro argument")) # blocks vs. tuples @test parse("()") == Expr(:tuple) @@ -351,7 +351,7 @@ parsehex(s) = parse(Int,s,16) # issue #17705 @test parse("2e3_") == Expr(:call, :*, 2e3, :_) @test parse("2e-3_") == Expr(:call, :*, 2e-3, :_) -@test parse("2e3_\"x\"") == Expr(:call, :*, 2e3, Expr(:macrocall, Symbol("@__str"), "x")) +@test parse("2e3_\"x\"") == Expr(:call, :*, 2e3, Expr(:macrocall, Symbol("@__str"), LineNumberNode(1, :none), "x")) # multibyte spaces @test parse(Int, "3\u2003\u202F") == 3 @@ -514,7 +514,7 @@ let b = IOBuffer(""" end f() """) - @test Base.parse_input_line(b) == Expr(:let, Expr(:block, Expr(:line, 2, :none), :x), Expr(:(=), :x, :x)) + @test Base.parse_input_line(b) == Expr(:let, Expr(:block, LineNumberNode(2, :none), :x), Expr(:(=), :x, :x)) @test Base.parse_input_line(b) == Expr(:call, :f) @test Base.parse_input_line(b) === nothing end @@ -574,7 +574,7 @@ f16517() = try error(); catch 0; end # issue #16671 @test parse("1.") === 1.0 -isline(x) = isa(x,Expr) && x.head === :line +isline(x) = isa(x, LineNumberNode) # issue #16672 @test count(isline, parse("begin end").args) == 1 @@ -584,9 +584,9 @@ isline(x) = isa(x,Expr) && x.head === :line # issue #16736 let - local lineoffset0 = @__LINE__ + 1 - local lineoffset1 = @__LINE__ - local lineoffset2 = @__LINE__ - 1 + local lineoffset0 = @__LINE__() + 1 + local lineoffset1 = @__LINE__() + local lineoffset2 = @__LINE__() - 1 @test lineoffset0 == lineoffset1 == lineoffset2 end @@ -596,13 +596,13 @@ end y end") == Expr(:try, Expr(:block, - Expr(:line, 1, :none), + LineNumberNode(1, :none), :x), false, Expr(:block, - Expr(:line, 2, :none), + LineNumberNode(2, :none), Expr(:call, :test), - Expr(:line, 3, :none), + LineNumberNode(3, :none), :y)) # test that pre 0.5 deprecated syntax is a parse error @@ -775,12 +775,12 @@ module B15838 end @test A15838.@f() === nothing @test A15838.@f(1) === :b -let nometh = expand(:(A15838.@f(1, 2))) +let nometh = expand(:(A15838.@f(1, 2))), __source__ = LineNumberNode(@__LINE__, Symbol(@__FILE__)) @test (nometh::Expr).head === :error @test length(nometh.args) == 1 e = nometh.args[1]::MethodError @test e.f === getfield(A15838, Symbol("@f")) - @test e.args === (1,2) + @test e.args === (__source__, 1, 2) end # issue 10046 @@ -904,8 +904,8 @@ f1_exprs = get_expr_list(@code_typed(f1(1))[1]) f2_exprs = get_expr_list(@code_typed(f2(1))[1]) @test Meta.isexpr(f1_exprs[end], :return) -@test is_pop_loc(f2_exprs[end - 1]) -@test Meta.isexpr(f2_exprs[end], :return) +@test is_pop_loc(f2_exprs[end]) +@test Meta.isexpr(f2_exprs[end - 1], :return) if Base.JLOptions().code_coverage != 0 && Base.JLOptions().can_inline != 0 @test count_meta_loc(f1_exprs) == 1 @@ -924,10 +924,10 @@ end @test :(x`s\`"\x\$\\`) == :(@x_cmd "s`\"\\x\\\$\\\\") # Check multiline command literals -@test :``` +@test :(@cmd "multiline\ncommand\n") == :``` multiline command -``` == :(@cmd "multiline\ncommand\n") +``` macro julia_cmd(s) Meta.quot(parse(s)) @@ -980,7 +980,7 @@ let ..(x,y) = x + y end # issue #7669 -@test parse("@a(b=1, c=2)") == Expr(:macrocall, Symbol("@a"), :(b=1), :(c=2)) +@test parse("@a(b=1, c=2)") == Expr(:macrocall, Symbol("@a"), LineNumberNode(1, :none), :(b=1), :(c=2)) # issue #19685 let f = function (x; kw...) @@ -1070,7 +1070,7 @@ end @test expand(:(@err20000)) == Expr(:error, "oops!") # issue #20000 -@test parse("@m(a; b=c)") == Expr(:macrocall, Symbol("@m"), +@test parse("@m(a; b=c)") == Expr(:macrocall, Symbol("@m"), LineNumberNode(1, :none), Expr(:parameters, Expr(:kw, :b, :c)), :a) # issue #21054 diff --git a/test/printf.jl b/test/printf.jl index 4a50982aa368bc..2885ddc8df3bd2 100644 --- a/test/printf.jl +++ b/test/printf.jl @@ -25,8 +25,9 @@ for (fmt, val) in (("%i", "42"), ("%f", "42.000000"), ("%g", "42")), num in (UInt16(42), UInt32(42), UInt64(42), UInt128(42), - Int16(42), Int32(42), Int64(42), Int128(42)) + Int16(42), Int32(42), Int64(42), Int128(42), big"42") #big"42" causes stack overflow on %a ; gh #14409 + num isa BigInt && fmt in ["%a", "%#o", "%g"] && continue @test @eval(@sprintf($fmt, $num) == $val) end @@ -255,3 +256,6 @@ end # @printf @test_throws ArgumentError eval(:(@printf 1)) + +# Check bug with trailing nul printing BigFloat +@test (@sprintf("%.330f", BigFloat(1)))[end] != '\0' diff --git a/test/random.jl b/test/random.jl index 0d54f0a426cc4e..79bbc7ecb21266 100644 --- a/test/random.jl +++ b/test/random.jl @@ -53,12 +53,6 @@ let mt = MersenneTwister(0) rand(coll, 2, 3) end -# rand using Dict, Set -adict = Dict(1=>2, 3=>4, 5=>6) -@test rand(adict) in adict -aset = Set(1:10) -@test rand(aset) in aset - # randn @test randn(MersenneTwister(42)) == -0.5560268761463861 A = zeros(2, 2) @@ -315,6 +309,11 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) ftypes = [Float16, Float32, Float64] cftypes = [Complex32, Complex64, Complex128, ftypes...] types = [Bool, Char, Base.BitInteger_types..., ftypes...] + collections = [(IntSet(rand(1:100, 20)), Int), + (Set(rand(Int, 20)), Int), + (Dict(zip(rand(Int,10), rand(Int, 10))), Pair{Int,Int}), + (1:100, Int), + (rand(Int, 100), Int)] b2 = big(2) u3 = UInt(3) for f in [rand, randn, randexp] @@ -336,6 +335,20 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) end end end + for (C, T) in collections + a0 = rand(rng..., C) ::T + a1 = rand(rng..., C, 5) ::Vector{T} + a2 = rand(rng..., C, 2, 3) ::Array{T, 2} + a3 = rand!(rng..., Array{T}(5), C) ::Vector{T} + a4 = rand!(rng..., Array{T}(2, 3), C) ::Array{T, 2} + for a in [a0, a1..., a2..., a3..., a4...] + @test a in C + end + end + for C in [1:0, Dict(), Set(), IntSet(), Int[]] + @test_throws ArgumentError rand(rng..., C) + @test_throws ArgumentError rand(rng..., C, 5) + end for f! in [rand!, randn!, randexp!] for T in (f! === rand! ? types : f! === randn! ? cftypes : ftypes) X = T == Bool ? T[0,1] : T[0,1,2] diff --git a/test/reduce.jl b/test/reduce.jl index 74a4c72eee0301..cf89d564262f8f 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -362,3 +362,6 @@ end test18695(r) = sum( t^2 for t in r ) @test @inferred(test18695([1.0,2.0,3.0,4.0])) == 30.0 @test_throws ArgumentError test18695(Any[]) + +# issue #21107 +@test foldr(-,2:2) == 2 diff --git a/test/reflection.jl b/test/reflection.jl index d66098e3fde77b..0e00763f70c26c 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -337,7 +337,7 @@ end return true end end -@test functionloc(f14346)[2] == @__LINE__-4 +@test functionloc(f14346)[2] == @__LINE__() - 4 # test jl_get_llvm_fptr. We test functions both in and definitely not in the system image definitely_not_in_sysimg() = nothing @@ -366,10 +366,10 @@ let using .MacroTest a = 1 m = getfield(current_module(), Symbol("@macrotest")) - @test which(m, Tuple{Int,Symbol})==@which @macrotest 1 a - @test which(m, Tuple{Int,Int})==@which @macrotest 1 1 + @test which(m, Tuple{LineNumberNode, Int, Symbol}) == @which @macrotest 1 a + @test which(m, Tuple{LineNumberNode, Int, Int}) == @which @macrotest 1 1 - @test first(methods(m,Tuple{Int, Int}))==@which MacroTest.@macrotest 1 1 + @test first(methods(m, Tuple{LineNumberNode, Int, Int})) == @which MacroTest.@macrotest 1 1 @test functionloc(@which @macrotest 1 1) == @functionloc @macrotest 1 1 end diff --git a/test/replutil.jl b/test/replutil.jl index 63e3091c9b7a7c..ac4bec2258976c 100644 --- a/test/replutil.jl +++ b/test/replutil.jl @@ -12,7 +12,7 @@ function test_have_color(buf, color, no_color) end cfile = " at $(@__FILE__):" -c1line = @__LINE__ + 1 +c1line = @__LINE__() + 1 method_c1(x::Float64, s::AbstractString...) = true buf = IOBuffer() @@ -59,7 +59,7 @@ color = "\e[0m\nClosest candidates are:\n method_c2(\e[1m\e[31m::Int32\e[0m, :: no_color = no_color = "\nClosest candidates are:\n method_c2(!Matched::Int32, ::Float64, ::Any...)$cfile$(c2line+2)\n method_c2(!Matched::Int32, ::Any...)$cfile$(c2line+1)\n method_c2(::T<:Real, ::T<:Real, !Matched::T<:Real) where T<:Real$cfile$(c2line+5)\n ..." test_have_color(buf, color, no_color) -c3line = @__LINE__ + 1 +c3line = @__LINE__() + 1 method_c3(x::Float64, y::Float64) = true Base.show_method_candidates(buf, Base.MethodError(method_c3,(1.,))) color = "\e[0m\nClosest candidates are:\n method_c3(::Float64, \e[1m\e[31m::Float64\e[0m)$cfile$c3line\e[0m" @@ -75,7 +75,7 @@ test_have_color(buf, "\e[0m\nClosest candidates are:\n method_c4(::AbstractString)$cfile$(c4line+2)\n method_c4()$cfile$(c4line+1)\e[0m", "\nClosest candidates are:\n method_c4(::AbstractString)$cfile$(c4line+2)\n method_c4()$cfile$(c4line+1)") -c5line = @__LINE__ + 1 +c5line = @__LINE__() + 1 method_c5(::Type{Float64}) = true Base.show_method_candidates(buf, MethodError(method_c5,(Float64,))) test_have_color(buf, "\e[0m\nClosest candidates are:\n method_c5(::Type{Float64})$cfile$c5line\e[0m", @@ -92,12 +92,12 @@ for f in [getindex, setindex!] test_have_color(buf, "", "") end -PR16155line = @__LINE__ + 2 +PR16155line = @__LINE__() + 2 mutable struct PR16155 a::Int64 b end -PR16155line2 = @__LINE__ + 1 +PR16155line2 = @__LINE__() + 1 (::Type{T}){T<:PR16155}(arg::Any) = "replace call-to-convert method from sysimg" Base.show_method_candidates(buf, MethodError(PR16155,(1.0, 2.0, Int64(3)))) @@ -146,12 +146,12 @@ else @test contains(error_out3, "method_c6_in_module(::Any; y)$cfile$(c6mline + 3) got unsupported keyword argument \"x\"") end -c7line = @__LINE__ + 1 +c7line = @__LINE__() + 1 method_c7(a, b; kargs...) = a Base.show_method_candidates(buf, MethodError(method_c7, (1, 1)), [(:x, 1), (:y, 2)]) test_have_color(buf, "\e[0m\nClosest candidates are:\n method_c7(::Any, ::Any; kargs...)$cfile$c7line\e[0m", "\nClosest candidates are:\n method_c7(::Any, ::Any; kargs...)$cfile$c7line") -c8line = @__LINE__ + 1 +c8line = @__LINE__() + 1 method_c8(a, b; y=1, w=1) = a Base.show_method_candidates(buf, MethodError(method_c8, (1, 1)), [(:x, 1), (:y, 2), (:z, 1), (:w, 1)]) test_have_color(buf, "\e[0m\nClosest candidates are:\n method_c8(::Any, ::Any; y, w)$cfile$c8line\e[1m\e[31m got unsupported keyword arguments \"x\", \"z\"\e[0m\e[0m", @@ -344,7 +344,7 @@ end @test stringmime("text/plain", FunctionLike()) == "(::FunctionLike) (generic function with 0 methods)" @test ismatch(r"^@doc \(macro with \d+ method[s]?\)$", stringmime("text/plain", getfield(Base, Symbol("@doc")))) -method_defs_lineno = @__LINE__+1 +method_defs_lineno = @__LINE__() + 1 Base.Symbol() = throw(ErrorException("1")) (::Symbol)() = throw(ErrorException("2")) EightBitType() = throw(ErrorException("3")) @@ -361,15 +361,24 @@ let err_str, sp = Base.source_path() sn = basename(sp) - @test sprint(show, which(Symbol, Tuple{})) == "Symbol() in $curmod_str at $sp:$(method_defs_lineno + 0)" - @test sprint(show, which(:a, Tuple{})) == "(::Symbol)() in $curmod_str at $sp:$(method_defs_lineno + 1)" - @test sprint(show, which(EightBitType, Tuple{})) == "$(curmod_prefix)EightBitType() in $curmod_str at $sp:$(method_defs_lineno + 2)" - @test sprint(show, which(reinterpret(EightBitType, 0x54), Tuple{})) == "(::$(curmod_prefix)EightBitType)() in $curmod_str at $sp:$(method_defs_lineno + 3)" - @test sprint(show, which(EightBitTypeT, Tuple{})) == "(::Type{$(curmod_prefix)EightBitTypeT})() in $curmod_str at $sp:$(method_defs_lineno + 4)" - @test sprint(show, which(EightBitTypeT{Int32}, Tuple{})) == "(::Type{$(curmod_prefix)EightBitTypeT{T}})() where T in $curmod_str at $sp:$(method_defs_lineno + 5)" - @test sprint(show, which(reinterpret(EightBitTypeT{Int32}, 0x54), Tuple{})) == "(::$(curmod_prefix)EightBitTypeT)() in $curmod_str at $sp:$(method_defs_lineno + 6)" - @test startswith(sprint(show, which(getfield(Base, Symbol("@doc")), Tuple{Vararg{Any}})), "@doc(x...) in Core at boot.jl:") - @test startswith(sprint(show, which(FunctionLike(), Tuple{})), "(::$(curmod_prefix)FunctionLike)() in $curmod_str at $sp:$(method_defs_lineno + 7)") + @test sprint(show, which(Symbol, Tuple{})) == + "Symbol() in $curmod_str at $sp:$(method_defs_lineno + 0)" + @test sprint(show, which(:a, Tuple{})) == + "(::Symbol)() in $curmod_str at $sp:$(method_defs_lineno + 1)" + @test sprint(show, which(EightBitType, Tuple{})) == + "$(curmod_prefix)EightBitType() in $curmod_str at $sp:$(method_defs_lineno + 2)" + @test sprint(show, which(reinterpret(EightBitType, 0x54), Tuple{})) == + "(::$(curmod_prefix)EightBitType)() in $curmod_str at $sp:$(method_defs_lineno + 3)" + @test sprint(show, which(EightBitTypeT, Tuple{})) == + "(::Type{$(curmod_prefix)EightBitTypeT})() in $curmod_str at $sp:$(method_defs_lineno + 4)" + @test sprint(show, which(EightBitTypeT{Int32}, Tuple{})) == + "(::Type{$(curmod_prefix)EightBitTypeT{T}})() where T in $curmod_str at $sp:$(method_defs_lineno + 5)" + @test sprint(show, which(reinterpret(EightBitTypeT{Int32}, 0x54), Tuple{})) == + "(::$(curmod_prefix)EightBitTypeT)() in $curmod_str at $sp:$(method_defs_lineno + 6)" + @test startswith(sprint(show, which(getfield(Base, Symbol("@doc")), Tuple{LineNumberNode, Vararg{Any}})), + "@doc(__source__::LineNumberNode, x...) in Core at boot.jl:") + @test startswith(sprint(show, which(FunctionLike(), Tuple{})), + "(::$(curmod_prefix)FunctionLike)() in $curmod_str at $sp:$(method_defs_lineno + 7)") @test stringmime("text/plain", FunctionLike()) == "(::FunctionLike) (generic function with 1 method)" @test stringmime("text/plain", Core.arraysize) == "arraysize (built-in function)" diff --git a/test/show.jl b/test/show.jl index 44e3cca5a31996..ca12dd1c8d336a 100644 --- a/test/show.jl +++ b/test/show.jl @@ -15,8 +15,8 @@ struct T5589 end @test replstr(T5589(Array{String,1}(100))) == "$(curmod_prefix)T5589(String[#undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef … #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef])" -@test replstr(parse("mutable struct X end")) == ":(mutable struct X # none, line 1:\n end)" -@test replstr(parse("struct X end")) == ":(struct X # none, line 1:\n end)" +@test replstr(parse("mutable struct X end")) == ":(mutable struct X\n #= none:1 =#\n end)" +@test replstr(parse("struct X end")) == ":(struct X\n #= none:1 =#\n end)" s = "ccall(:f, Int, (Ptr{Void},), &x)" @test replstr(parse(s)) == ":($s)" @@ -42,12 +42,14 @@ macro test_repr(x) local x1 = parse($x) local x2 = eval(parse(repr(x1))) local x3 = eval(parse(repr(x2))) - x3 == x1 ? nothing : error(string( - "repr test failed:", - "\noriginal: ", $x, - "\n\nparsed: ", x2, "\n", sprint(dump, x2), - "\n\nreparsed: ", x3, "\n", sprint(dump, x3) - )) + if x3 != x1 + error(string( + "repr test failed:", + "\noriginal: ", $x, + "\n\nparsed: ", x2, "\n", sprint(dump, x2), + "\n\nreparsed: ", x3, "\n", sprint(dump, x3) + )) + end end end end @@ -94,76 +96,128 @@ end # control structures (shamelessly stolen from base/bitarray.jl) @test_repr """mutable struct BitArray{N} <: AbstractArray{Bool, N} + # line meta chunks::Vector{UInt64} + # line meta len::Int + # line meta dims::NTuple{N,Int} + # line meta function BitArray(dims::Int...) + # line meta if length(dims) != N + # line meta error(\"number of dimensions must be \$N (got \$(length(dims)))\") end + # line meta n = 1 + # line meta for d in dims + # line meta if d < 0 + # line meta error(\"dimension size must be nonnegative (got \$d)\") end + # line meta n *= d end + # line meta nc = num_bit_chunks(n) + # line meta chunks = Array{UInt64,1}(nc) + # line meta if nc > 0 + # line meta chunks[end] = UInt64(0) end + # line meta b = new(chunks, n) + # line meta if N != 1 + # line meta b.dims = dims end + # line meta return b end end""" @test_repr """function copy_chunks(dest::Vector{UInt64}, pos_d::Integer, src::Vector{UInt64}, pos_s::Integer, numbits::Integer) + # line meta if numbits == 0 + # line meta return end + # line meta if dest === src && pos_d > pos_s + # line meta return copy_chunks_rtol(dest, pos_d, pos_s, numbits) end + # line meta kd0, ld0 = get_chunks_id(pos_d) + # line meta kd1, ld1 = get_chunks_id(pos_d + numbits - 1) + # line meta ks0, ls0 = get_chunks_id(pos_s) + # line meta ks1, ls1 = get_chunks_id(pos_s + numbits - 1) + # line meta delta_kd = kd1 - kd0 + # line meta delta_ks = ks1 - ks0 + # line meta u = _msk64 + # line meta if delta_kd == 0 + # line meta msk_d0 = ~(u << ld0) | (u << ld1 << 1) else + # line meta msk_d0 = ~(u << ld0) + # line meta msk_d1 = (u << ld1 << 1) end + # line meta if delta_ks == 0 + # line meta msk_s0 = (u << ls0) & ~(u << ls1 << 1) else + # line meta msk_s0 = (u << ls0) end + # line meta chunk_s0 = glue_src_bitchunks(src, ks0, ks1, msk_s0, ls0) + # line meta dest[kd0] = (dest[kd0] & msk_d0) | ((chunk_s0 << ld0) & ~msk_d0) + # line meta if delta_kd == 0 + # line meta return end + # line meta for i = 1 : kd1 - kd0 - 1 + # line meta chunk_s1 = glue_src_bitchunks(src, ks0 + i, ks1, msk_s0, ls0) + # line meta chunk_s = (chunk_s0 >>> (63 - ld0) >>> 1) | (chunk_s1 << ld0) + # line meta dest[kd0 + i] = chunk_s + # line meta chunk_s0 = chunk_s1 end + # line meta if ks1 >= ks0 + delta_kd + # line meta chunk_s1 = glue_src_bitchunks(src, ks0 + delta_kd, ks1, msk_s0, ls0) else + # line meta chunk_s1 = UInt64(0) end + # line meta chunk_s = (chunk_s0 >>> (63 - ld0) >>> 1) | (chunk_s1 << ld0) + # line meta dest[kd1] = (dest[kd1] & msk_d1) | (chunk_s & ~msk_d1) + # line meta return end""" @@ -201,13 +255,21 @@ end""" @test_repr "[1 2 3; 4 5 6; 7 8 9]'" @test_repr "baremodule X +# line meta +# line meta importall ..A.b +# line meta import ...B.c +# line meta import D +# line meta import B.C.D.E.F.g end" @test_repr "baremodule Y +# line meta +# line meta export A, B, C +# line meta export D, E, F end" @@ -261,22 +323,22 @@ end @test string(:(-{x})) == "-{x}" # issue #11393 -@test_repr "@m(x,y) + z" -@test_repr "(@m(x,y),z)" -@test_repr "[@m(x,y),z]" -@test_repr "A[@m(x,y),z]" -@test_repr "T{@m(x,y),z}" +@test_repr "@m(x, y) + z" +@test_repr "(@m(x, y), z)" +@test_repr "[@m(x, y), z]" +@test_repr "A[@m(x, y), z]" +@test_repr "T{@m(x, y), z}" @test_repr "@m x @n(y) z" -@test_repr "f(@m(x,y);z=@n(a))" -@test_repr "@m(x,y).z" -@test_repr "::@m(x,y)+z" +@test_repr "f(@m(x, y); z=@n(a))" +@test_repr "@m(x, y).z" +@test_repr "::@m(x, y) + z" @test_repr "[@m(x) y z]" @test_repr "[@m(x) y; z]" @test_repr "let @m(x), y=z; end" -@test repr(:(@m x y)) == ":(@m x y)" -@test string(:(@m x y)) == "@m x y" -@test string(:(@m x y;)) == "begin \n @m x y\nend" +@test repr(:(@m x y)) == ":(#= $(@__FILE__):$(@__LINE__) =# @m x y)" +@test string(:(@m x y)) == "#= $(@__FILE__):$(@__LINE__) =# @m x y" +@test string(:(@m x y;)) == "begin\n #= $(@__FILE__):$(@__LINE__) =# @m x y\nend" # issue #11436 @test_repr "1 => 2 => 3" @@ -447,25 +509,33 @@ end # issue #15309 -l1, l2, l2n = Expr(:line,42), Expr(:line,42,:myfile), LineNumberNode(42) -@test string(l2n) == " # line 42:" -@test string(l2) == " # myfile, line 42:" -@test string(l1) == string(l2n) -ex = Expr(:block, l1, :x, l2, :y, l2n, :z) -@test replace(string(ex)," ","") == replace(""" -begin # line 42: - x # myfile, line 42: - y # line 42: - z -end""", " ", "") +let ex, + l1 = Expr(:line, 42), + l2 = Expr(:line, 42, :myfile), + l2n = LineNumberNode(42) + @test string(l2n) == "#= line 42 =#" + @test string(l2) == "#= myfile:42 =#" + @test string(l1) == string(l2n) + ex = Expr(:block, l1, :x, l2, :y, l2n, :z) + @test replace(string(ex)," ","") == replace(""" + begin + #= line 42 =# + x + #= myfile:42 =# + y + #= line 42 =# + z + end""", " ", "") +end # Test the printing of whatever form of line number representation # that is used in the arguments to a macro looks the same as for # regular quoting macro strquote(ex) - QuoteNode(string(ex)) + return QuoteNode(string(ex)) +end +let str_ex2a = @strquote(begin x end), str_ex2b = string(quote x end) + @test str_ex2a == str_ex2b end -str_ex2a, str_ex2b = @strquote(begin x end), string(quote x end) -@test str_ex2a == str_ex2b # test structured zero matrix printing for select structured types diff --git a/test/sparse/sparse.jl b/test/sparse/sparse.jl index 43a0c4c3465774..e22c0b7fe1d0dc 100644 --- a/test/sparse/sparse.jl +++ b/test/sparse/sparse.jl @@ -538,10 +538,12 @@ end @test tan.(Afull) == Array(tan.(A)) # should be redundant with sin test @test ceil.(Afull) == Array(ceil.(A)) @test floor.(Afull) == Array(floor.(A)) # should be redundant with ceil test - @test real.(Afull) == Array(real.(A)) - @test imag.(Afull) == Array(imag.(A)) - @test real.(Cfull) == Array(real.(C)) - @test imag.(Cfull) == Array(imag.(C)) + @test real.(Afull) == Array(real.(A)) == Array(real(A)) + @test imag.(Afull) == Array(imag.(A)) == Array(imag(A)) + @test conj.(Afull) == Array(conj.(A)) == Array(conj(A)) + @test real.(Cfull) == Array(real.(C)) == Array(real(C)) + @test imag.(Cfull) == Array(imag.(C)) == Array(imag(C)) + @test conj.(Cfull) == Array(conj.(C)) == Array(conj(C)) # Test representatives of [unary functions that map zeros to zeros and nonzeros to nonzeros] @test expm1.(Afull) == Array(expm1.(A)) @test abs.(Afull) == Array(abs.(A)) @@ -559,12 +561,19 @@ end I = rand(T[1:100;], 2, 2) D = R + I*im S = sparse(D) - @test R == real.(S) - @test I == imag.(S) - @test real.(sparse(R)) == R - @test nnz(imag.(sparse(R))) == 0 + spR = sparse(R) + + @test R == real.(S) == real(S) + @test I == imag.(S) == imag(S) + @test conj(full(S)) == conj.(S) == conj(S) + @test real.(spR) == R + @test nnz(imag.(spR)) == nnz(imag(spR)) == 0 @test abs.(S) == abs.(D) @test abs2.(S) == abs2.(D) + + # test aliasing of real and conj of real valued matrix + @test real(spR) === spR + @test conj(spR) === spR end end diff --git a/test/sparse/sparsevector.jl b/test/sparse/sparsevector.jl index 543b7668160fd3..77024341a19ba5 100644 --- a/test/sparse/sparsevector.jl +++ b/test/sparse/sparsevector.jl @@ -637,14 +637,16 @@ let x = spv_x1, x2 = spv_x2 @test exact_equal(complex.(x2, x), SparseVector(8, [1,2,5,6,7], [3.25+0.0im, 4.0+1.25im, -0.75im, -5.5+3.5im, -6.0+0.0im])) - # real & imag + # real, imag and conj @test real(x) === x @test exact_equal(imag(x), spzeros(Float64, length(x))) + @test conj(x) === x xcp = complex.(x, x2) @test exact_equal(real(xcp), x) @test exact_equal(imag(xcp), x2) + @test exact_equal(conj(xcp), complex.(x, -x2)) end ### Zero-preserving math functions: sparse -> sparse diff --git a/test/stacktraces.jl b/test/stacktraces.jl index ac1814354f12c2..19e23aa0f18f1f 100644 --- a/test/stacktraces.jl +++ b/test/stacktraces.jl @@ -6,7 +6,7 @@ let @noinline child() = stacktrace() @noinline parent() = child() @noinline grandparent() = parent() - line_numbers = @__LINE__ - [3, 2, 1] + line_numbers = @__LINE__() - [3, 2, 1] stack = grandparent() # Basic tests. @@ -68,7 +68,7 @@ let ct = current_task() return catch_stacktrace() end end - line_numbers = @__LINE__ .- [15, 10, 5] + line_numbers = @__LINE__() .- [15, 10, 5] # Test try...catch with stacktrace @test try_stacktrace()[1] == StackFrame(:try_stacktrace, @__FILE__, line_numbers[2]) diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 4c155f92b1b270..551d46305d0f8e 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -194,7 +194,7 @@ gstr = GenericString("12") @test ind2chr(gstr,2)==2 # issue #10307 -@test typeof(map(Int16,AbstractString[])) == Vector{Int16} +@test typeof(map(x -> parse(Int16, x), AbstractString[])) == Vector{Int16} for T in [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128] for i in [typemax(T), typemin(T)] diff --git a/test/subarray.jl b/test/subarray.jl index fb2d8d8300017a..45d31b6fe3ecdf 100644 --- a/test/subarray.jl +++ b/test/subarray.jl @@ -555,3 +555,11 @@ let @test Base.IndexStyle(view(a, :, :)) == Base.IndexLinear() @test isbits(view(a, :, :)) end + +# Issue #17351 +let + x = rand(10) + u = rand(10, 3) + su = view(u, :, 1) + @test size(@inferred(xcorr(x, su))) == (19,) +end diff --git a/test/worlds.jl b/test/worlds.jl index 13bb28597c0906..1dfea7f6fe8d9c 100644 --- a/test/worlds.jl +++ b/test/worlds.jl @@ -136,7 +136,7 @@ f265(::Int) = 1 # test for method errors h265() = true -loc_h265 = "$(Base.source_path()):$(@__LINE__ - 1)" +loc_h265 = "$(@__FILE__):$(@__LINE__() - 1)" @test h265() @test_throws MethodError put_n_take!(h265, ()) @test_throws MethodError wait(t265)