From 7fb758a275a0b4cf0e3f4cbf482c065cb32f0011 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Sun, 5 Feb 2017 19:20:03 -0500 Subject: [PATCH] WIP: add oneunit(x) for dimensionful version of one(x) (#20268) add oneunit(x) for dimensionful version of one(x), and change one -> oneunit where appropriate. --- NEWS.md | 3 ++ base/Enums.jl | 2 +- base/array.jl | 13 ++++--- base/bool.jl | 2 +- base/deprecated.jl | 4 +-- base/dft.jl | 8 ++--- base/exports.jl | 1 + base/fft/FFTW.jl | 2 +- base/intfuncs.jl | 4 +-- base/iterators.jl | 2 +- base/linalg/dense.jl | 2 +- base/linalg/factorization.jl | 2 +- base/linalg/generic.jl | 7 ++-- base/linalg/givens.jl | 47 +++++++++++++----------- base/linalg/hessenberg.jl | 2 +- base/linalg/linalg.jl | 2 +- base/linalg/qr.jl | 2 +- base/linalg/triangular.jl | 28 +++++++-------- base/linalg/uniformscaling.jl | 2 ++ base/number.jl | 58 ++++++++++++++++++++++++++---- base/random.jl | 8 ++--- base/range.jl | 20 +++++------ base/set.jl | 2 +- base/sort.jl | 6 ++-- base/sparse/higherorderfns.jl | 56 ++++++++++++++--------------- base/sparse/linalg.jl | 4 +-- base/sparse/sparsematrix.jl | 2 +- base/sparse/sparsevector.jl | 4 +-- base/special/gamma.jl | 2 +- base/statistics.jl | 2 +- doc/src/manual/performance-tips.md | 3 +- doc/src/manual/style-guide.md | 16 ++++----- doc/src/stdlib/numbers.md | 1 + 33 files changed, 191 insertions(+), 128 deletions(-) diff --git a/NEWS.md b/NEWS.md index 35531dbdf0359..29efbed34761d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -180,6 +180,9 @@ Library improvements * `max`, `min`, and related functions (`minmax`, `maximum`, `minimum`, `extrema`) now return `NaN` for `NaN` arguments ([#12563]). + * `oneunit(x)` function to return a dimensionful version of `one(x)` (which + is clarified to mean a dimensionless quantity if `x` is dimensionful) ([#20268]). + * The `chop` and `chomp` functions now return a `SubString` ([#18339]). * Numbered stackframes printed in stacktraces can be opened in an editor by diff --git a/base/Enums.jl b/base/Enums.jl index 14c9a1b9f3971..4a4ceabf16049 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -95,7 +95,7 @@ macro enum(T,syms...) lo = min(lo, i) hi = max(hi, i) end - i += one(i) + i += oneunit(i) end values = basetype[i[2] for i in vals] if hasexpr && values != unique(values) diff --git a/base/array.jl b/base/array.jl index a06c36b76c5f1..959e90033c2cf 100644 --- a/base/array.jl +++ b/base/array.jl @@ -237,10 +237,10 @@ end `m`-by-`n` identity matrix. The default element type is `Float64`. """ -function eye(T::Type, m::Integer, n::Integer) +function eye{T}(::Type{T}, m::Integer, n::Integer) a = zeros(T,m,n) for i = 1:min(m,n) - a[i,i] = one(T) + a[i,i] = oneunit(T) end return a end @@ -251,7 +251,7 @@ end `m`-by-`n` identity matrix. """ eye(m::Integer, n::Integer) = eye(Float64, m, n) -eye(T::Type, n::Integer) = eye(T, n, n) +eye{T}(::Type{T}, n::Integer) = eye(T, n, n) """ eye([T::Type=Float64,] n::Integer) @@ -281,14 +281,17 @@ julia> eye(A) Note the difference from [`ones`](@ref). """ -eye{T}(x::AbstractMatrix{T}) = eye(T, size(x, 1), size(x, 2)) +eye{T}(x::AbstractMatrix{T}) = eye(typeof(one(T)), size(x, 1), size(x, 2)) -function one{T}(x::AbstractMatrix{T}) +function _one{T}(unit::T, x::AbstractMatrix) m,n = size(x) m==n || throw(DimensionMismatch("multiplicative identity defined only for square matrices")) eye(T, m) end +one{T}(x::AbstractMatrix{T}) = _one(one(T), x) +oneunit{T}(x::AbstractMatrix{T}) = _one(oneunit(T), x) + ## Conversions ## convert{T}(::Type{Vector}, x::AbstractVector{T}) = convert(Vector{T}, x) diff --git a/base/bool.jl b/base/bool.jl index b65e56b0065db..b7b81df2f6148 100644 --- a/base/bool.jl +++ b/base/bool.jl @@ -93,7 +93,7 @@ iszero(x::Bool) = !x ^(x::Integer, y::Bool) = ifelse(y, x, one(x)) function +{T<:AbstractFloat}(x::Bool, y::T)::promote_type(Bool,T) - return ifelse(x, one(y) + y, y) + return ifelse(x, oneunit(y) + y, y) end +(y::AbstractFloat, x::Bool) = x + y diff --git a/base/deprecated.jl b/base/deprecated.jl index a2446d9628cc4..8bcff2e651423 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -141,7 +141,7 @@ function convert(::Type{Base.LinAlg.UnitUpperTriangular}, A::Diagonal) "that convert `Diagonal`/`Bidiagonal` to `<:AbstractTriangular` are deprecated. ", "Consider calling the `UnitUpperTriangular` constructor directly ", "(`Base.LinAlg.UnitUpperTriangular(A)`) instead."), :convert) - if !all(x -> x == one(x), A.diag) + if !all(x -> x == oneunit(x), A.diag) throw(ArgumentError("matrix cannot be represented as UnitUpperTriangular")) end Base.LinAlg.UnitUpperTriangular(Array(A)) @@ -151,7 +151,7 @@ function convert(::Type{Base.LinAlg.UnitLowerTriangular}, A::Diagonal) "that convert `Diagonal`/`Bidiagonal` to `<:AbstractTriangular` are deprecated. ", "Consider calling the `UnitLowerTriangular` constructor directly ", "(`Base.LinAlg.UnitLowerTriangular(A)`) instead."), :convert) - if !all(x -> x == one(x), A.diag) + if !all(x -> x == oneunit(x), A.diag) throw(ArgumentError("matrix cannot be represented as UnitLowerTriangular")) end Base.LinAlg.UnitLowerTriangular(Array(A)) diff --git a/base/dft.jl b/base/dft.jl index 5ffeeaa46467f..b676dee045b85 100644 --- a/base/dft.jl +++ b/base/dft.jl @@ -33,10 +33,10 @@ realfloat{T<:FFTWFloat}(x::StridedArray{T}) = x # return an Array, rather than similar(x), to avoid an extra copy for FFTW # (which only works on StridedArray types). -complexfloat{T<:Complex}(x::AbstractArray{T}) = copy1(typeof(fftwfloat(one(T))), x) -complexfloat{T<:Real}(x::AbstractArray{T}) = copy1(typeof(complex(fftwfloat(one(T)))), x) +complexfloat{T<:Complex}(x::AbstractArray{T}) = copy1(typeof(fftwfloat(zero(T))), x) +complexfloat{T<:Real}(x::AbstractArray{T}) = copy1(typeof(complex(fftwfloat(zero(T)))), x) -realfloat{T<:Real}(x::AbstractArray{T}) = copy1(typeof(fftwfloat(one(T))), x) +realfloat{T<:Real}(x::AbstractArray{T}) = copy1(typeof(fftwfloat(zero(T))), x) # copy to a 1-based array, using circular permutation function copy1{T}(::Type{T}, x) @@ -262,7 +262,7 @@ summary(p::ScaledPlan) = string(p.scale, " * ", summary(p.p)) *(p::Plan, I::UniformScaling) = ScaledPlan(p, I.λ) # Normalization for ifft, given unscaled bfft, is 1/prod(dimensions) -normalization(T, sz, region) = (one(T) / prod([sz...][[region...]]))::T +normalization(T, sz, region) = one(T) / Int(prod([sz...][[region...]])) normalization(X, region) = normalization(real(eltype(X)), size(X), region) plan_ifft(x::AbstractArray, region; kws...) = diff --git a/base/exports.jl b/base/exports.jl index 3e1ffb369e7b9..78b9ee477cc2b 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -382,6 +382,7 @@ export numerator, num2hex, one, + oneunit, powermod, prevfloat, prevpow, diff --git a/base/fft/FFTW.jl b/base/fft/FFTW.jl index c33fe02874472..502399f9a4398 100644 --- a/base/fft/FFTW.jl +++ b/base/fft/FFTW.jl @@ -568,7 +568,7 @@ end # (FIXME: is there a way to use the Julia promotion rules more cleverly here?) fftwcomplex{T<:fftwComplex}(X::StridedArray{T}) = X fftwcomplex{T<:fftwReal}(X::AbstractArray{T}) = - copy!(Array{typeof(complex(one(T)))}(size(X)), X) + copy!(Array{typeof(complex(zero(T)))}(size(X)), X) fftwcomplex{T<:Real}(X::AbstractArray{T}) = copy!(Array{Complex128}(size(X)),X) fftwcomplex{T<:Complex}(X::AbstractArray{T}) = copy!(Array{Complex128}(size(X)), X) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index bba4708fbce1a..bc305b48664d7 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -109,7 +109,7 @@ julia> gcdx(240, 46) """ function gcdx{T<:Integer}(a::T, b::T) # a0, b0 = a, b - s0, s1 = one(T), zero(T) + s0, s1 = oneunit(T), zero(T) t0, t1 = s1, s0 # The loop invariant is: s0*a0 + t0*b0 == a while b != 0 @@ -242,7 +242,7 @@ julia> nextpow2(17) 32 ``` """ -nextpow2(x::Unsigned) = one(x)<<((sizeof(x)<<3)-leading_zeros(x-one(x))) +nextpow2(x::Unsigned) = oneunit(x)<<((sizeof(x)<<3)-leading_zeros(x-oneunit(x))) nextpow2(x::Integer) = reinterpret(typeof(x),x < 0 ? -nextpow2(unsigned(-x)) : nextpow2(unsigned(x))) """ diff --git a/base/iterators.jl b/base/iterators.jl index a740e477795bc..30a864ce2a990 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -248,7 +248,7 @@ end An iterator that counts forever, starting at `start` and incrementing by `step`. """ countfrom(start::Number, step::Number) = Count(promote(start, step)...) -countfrom(start::Number) = Count(start, one(start)) +countfrom(start::Number) = Count(start, oneunit(start)) countfrom() = Count(1, 1) eltype{S}(::Type{Count{S}}) = S diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index 3c02b3395e0ae..2155312e8f497 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -165,7 +165,7 @@ tril(M::Matrix, k::Integer) = tril!(copy(M), k) function gradient(F::AbstractVector, h::Vector) n = length(F) - T = typeof(one(eltype(F))/one(eltype(h))) + T = typeof(oneunit(eltype(F))/oneunit(eltype(h))) g = similar(F, T) if n == 1 g[1] = zero(T) diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index 9a456a5be6057..ac581f5466a47 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -42,7 +42,7 @@ for (f1, f2) in ((:\, :A_ldiv_B!), (:Ac_ldiv_B, :Ac_ldiv_B!)) @eval begin function $f1(F::Factorization, B::AbstractVecOrMat) - TFB = typeof(one(eltype(F)) / one(eltype(B))) + TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F))) BB = similar(B, TFB, size(B)) copy!(BB, B) $f2(convert(Factorization{TFB}, F), BB) diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index 3ee643c384c05..946fbd6cfa17f 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -447,7 +447,7 @@ function vecnorm(itr, p::Real=2) vecnormp(itr,p) end end -@inline vecnorm(x::Number, p::Real=2) = p == 0 ? (x==0 ? zero(abs(x)) : one(abs(x))) : abs(x) +@inline vecnorm(x::Number, p::Real=2) = p == 0 ? (x==0 ? zero(abs(x)) : oneunit(abs(x))) : abs(x) norm(x::AbstractVector, p::Real=2) = vecnorm(x, p) @@ -719,8 +719,9 @@ true ``` """ function inv{T}(A::AbstractMatrix{T}) - S = typeof(zero(T)/one(T)) - A_ldiv_B!(factorize(convert(AbstractMatrix{S}, A)), eye(S, checksquare(A))) + S = typeof(zero(T)/one(T)) # dimensionful + S0 = typeof(zero(T)/oneunit(T)) # dimensionless + A_ldiv_B!(factorize(convert(AbstractMatrix{S}, A)), eye(S0, checksquare(A))) end """ diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index 8096347f9b1ce..7471df3a8c19c 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -55,14 +55,16 @@ realmin2{T}(::Type{T}) = (twopar = 2one(T); twopar^trunc(Integer,log(realmin(T)/ # Univ. of Colorado Denver # NAG Ltd. function givensAlgorithm{T<:AbstractFloat}(f::T, g::T) - zeropar = zero(T) onepar = one(T) twopar = 2one(T) + T0 = typeof(onepar) # dimensionless + zeropar = T0(zero(T)) # must be dimensionless - safmin = realmin(T) - epspar = eps(T) - safmn2 = realmin2(T) - safmx2 = onepar/safmn2 + # need both dimensionful and dimensionless versions of these: + safmn2 = realmin2(T0) + safmn2u = realmin2(T) + safmx2 = one(T)/safmn2 + safmx2u = oneunit(T)/safmn2 if g == 0 cs = onepar @@ -76,14 +78,14 @@ function givensAlgorithm{T<:AbstractFloat}(f::T, g::T) f1 = f g1 = g scalepar = max(abs(f1), abs(g1)) - if scalepar >= safmx2 + if scalepar >= safmx2u count = 0 while true count += 1 f1 *= safmn2 g1 *= safmn2 scalepar = max(abs(f1), abs(g1)) - if scalepar < safmx2 break end + if scalepar < safmx2u break end end r = sqrt(f1*f1 + g1*g1) cs = f1/r @@ -91,14 +93,14 @@ function givensAlgorithm{T<:AbstractFloat}(f::T, g::T) for i = 1:count r *= safmx2 end - elseif scalepar <= safmn2 + elseif scalepar <= safmn2u count = 0 while true count += 1 f1 *= safmx2 g1 *= safmx2 scalepar = max(abs(f1), abs(g1)) - if scalepar > safmn2 break end + if scalepar > safmn2u break end end r = sqrt(f1*f1 + g1*g1) cs = f1/r @@ -127,27 +129,30 @@ end # Univ. of Colorado Denver # NAG Ltd. function givensAlgorithm{T<:AbstractFloat}(f::Complex{T}, g::Complex{T}) - twopar, onepar, zeropar = 2one(T), one(T), zero(T) - czero = zero(Complex{T}) + twopar, onepar = 2one(T), one(T) + T0 = typeof(onepar) # dimensionless + zeropar = T0(zero(T)) # must be dimensionless + czero = complex(zeropar) abs1(ff) = max(abs(real(ff)), abs(imag(ff))) - safmin = realmin(T) - epspar = eps(T) - safmn2 = realmin2(T) - safmx2 = onepar/safmn2 + safmin = realmin(T0) + safmn2 = realmin2(T0) + safmn2u = realmin2(T) + safmx2 = one(T)/safmn2 + safmx2u = oneunit(T)/safmn2 scalepar = max(abs1(f), abs1(g)) fs = f gs = g count = 0 - if scalepar >= safmx2 + if scalepar >= safmx2u while true count += 1 fs *= safmn2 gs *= safmn2 scalepar *= safmn2 - if scalepar < safmx2 break end + if scalepar < safmx2u break end end - elseif scalepar <= safmn2 + elseif scalepar <= safmn2u if g == 0 cs = onepar sn = czero @@ -159,12 +164,12 @@ function givensAlgorithm{T<:AbstractFloat}(f::Complex{T}, g::Complex{T}) fs *= safmx2 gs *= safmx2 scalepar *= safmx2 - if scalepar > safmn2 break end + if scalepar > safmn2u break end end end f2 = abs2(fs) g2 = abs2(gs) - if f2 <= max(g2, onepar)*safmin + if f2 <= max(g2, oneunit(T))*safmin # This is a rare case: F is very small. @@ -305,7 +310,7 @@ function getindex(G::Givens, i::Integer, j::Integer) if i == G.i1 || i == G.i2 G.c else - one(G.c) + oneunit(G.c) end elseif i == G.i1 && j == G.i2 G.s diff --git a/base/linalg/hessenberg.jl b/base/linalg/hessenberg.jl index faa7c4813a569..a51aae6455091 100644 --- a/base/linalg/hessenberg.jl +++ b/base/linalg/hessenberg.jl @@ -48,7 +48,7 @@ julia> F[:Q] * F[:H] * F[:Q]' ``` """ function hessfact{T}(A::StridedMatrix{T}) - S = promote_type(Float32, typeof(one(T)/norm(one(T)))) + S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) return hessfact!(copy_oftype(A, S)) end diff --git a/base/linalg/linalg.jl b/base/linalg/linalg.jl index 2c0d94b7c19e0..9ccc8ae4c827a 100644 --- a/base/linalg/linalg.jl +++ b/base/linalg/linalg.jl @@ -8,7 +8,7 @@ import Base: A_mul_Bt, At_ldiv_Bt, A_rdiv_Bc, At_ldiv_B, Ac_mul_Bc, A_mul_Bc, Ac import Base: USE_BLAS64, abs, big, broadcast, ceil, conj, convert, copy, copy!, ctranspose, eltype, eye, findmax, findmin, fill!, floor, full, getindex, hcat, imag, indices, inv, isapprox, kron, length, linearindexing, map, - ndims, parent, power_by_squaring, print_matrix, promote_rule, real, round, + ndims, oneunit, parent, power_by_squaring, print_matrix, promote_rule, real, round, setindex!, show, similar, size, transpose, trunc, typed_hcat using Base: promote_op, _length, iszero, @pure, @propagate_inbounds, LinearFast, reduce, hvcat_fill, typed_vcat, promote_typeof diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index 2a62dec805da1..49464e75c5edc 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -246,7 +246,7 @@ function qr(v::AbstractVector) return __normalize!(vv, nrm), nrm else T = typeof(zero(eltype(v))/nrm) - return T[], one(T) + return T[], oneunit(T) end end diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index bcb02dc02440b..10446edbe908a 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -120,11 +120,11 @@ function full!{T,S}(A::UnitUpperTriangular{T,S}) end getindex{T,S}(A::UnitLowerTriangular{T,S}, i::Integer, j::Integer) = - i > j ? A.data[i,j] : ifelse(i == j, one(T), zero(T)) + i > j ? A.data[i,j] : ifelse(i == j, oneunit(T), zero(T)) getindex{T,S}(A::LowerTriangular{T,S}, i::Integer, j::Integer) = i >= j ? A.data[i,j] : zero(A.data[j,i]) getindex{T,S}(A::UnitUpperTriangular{T,S}, i::Integer, j::Integer) = - i < j ? A.data[i,j] : ifelse(i == j, one(T), zero(T)) + i < j ? A.data[i,j] : ifelse(i == j, oneunit(T), zero(T)) getindex{T,S}(A::UpperTriangular{T,S}, i::Integer, j::Integer) = i <= j ? A.data[i,j] : zero(A.data[j,i]) @@ -207,22 +207,22 @@ function tril!(A::UpperTriangular,k::Integer=0) end triu!(A::UpperTriangular,k::Integer=0) = UpperTriangular(triu!(A.data,k)) -function tril!(A::UnitUpperTriangular,k::Integer=0) +function tril!{T}(A::UnitUpperTriangular{T},k::Integer=0) n = size(A,1) if abs(k) > n throw(ArgumentError("requested diagonal, $k, out of bounds in matrix of size ($n,$n)")) elseif k < 0 - fill!(A.data,0) + fill!(A.data, zero(T)) return UpperTriangular(A.data) elseif k == 0 - fill!(A.data,0) + fill!(A.data, zero(T)) for i in diagind(A) - A.data[i] = one(eltype(A)) + A.data[i] = oneunit(T) end return UpperTriangular(A.data) else for i in diagind(A) - A.data[i] = one(eltype(A)) + A.data[i] = oneunit(T) end return UpperTriangular(tril!(A.data,k)) end @@ -230,7 +230,7 @@ end function triu!(A::UnitUpperTriangular,k::Integer=0) for i in diagind(A) - A.data[i] = one(eltype(A)) + A.data[i] = oneunit(eltype(A)) end return triu!(UpperTriangular(A.data),k) end @@ -254,22 +254,22 @@ end tril!(A::LowerTriangular,k::Integer=0) = LowerTriangular(tril!(A.data,k)) -function triu!(A::UnitLowerTriangular,k::Integer=0) +function triu!{T}(A::UnitLowerTriangular{T},k::Integer=0) n = size(A,1) if abs(k) > n throw(ArgumentError("requested diagonal, $k, out of bounds in matrix of size ($n,$n)")) elseif k > 0 - fill!(A.data,0) + fill!(A.data, zero(T)) return LowerTriangular(A.data) elseif k == 0 - fill!(A.data,0) + fill!(A.data, zero(T)) for i in diagind(A) - A.data[i] = one(eltype(A)) + A.data[i] = oneunit(T) end return LowerTriangular(A.data) else for i in diagind(A) - A.data[i] = one(eltype(A)) + A.data[i] = oneunit(T) end return LowerTriangular(triu!(A.data,k)) end @@ -277,7 +277,7 @@ end function tril!(A::UnitLowerTriangular,k::Integer=0) for i in diagind(A) - A.data[i] = one(eltype(A)) + A.data[i] = oneunit(eltype(A)) end return tril!(LowerTriangular(A.data),k) end diff --git a/base/linalg/uniformscaling.jl b/base/linalg/uniformscaling.jl index 583ec9435a6f5..bad9ddff58a5b 100644 --- a/base/linalg/uniformscaling.jl +++ b/base/linalg/uniformscaling.jl @@ -39,6 +39,8 @@ ctranspose(J::UniformScaling) = UniformScaling(conj(J.λ)) one{T}(::Type{UniformScaling{T}}) = UniformScaling(one(T)) one{T}(J::UniformScaling{T}) = one(UniformScaling{T}) +oneunit{T}(::Type{UniformScaling{T}}) = UniformScaling(oneunit(T)) +oneunit{T}(J::UniformScaling{T}) = oneunit(UniformScaling{T}) zero{T}(::Type{UniformScaling{T}}) = UniformScaling(zero(T)) zero{T}(J::UniformScaling{T}) = zero(UniformScaling{T}) diff --git a/base/number.jl b/base/number.jl index e2b04c633199a..e1fcd31f86c5c 100644 --- a/base/number.jl +++ b/base/number.jl @@ -76,9 +76,9 @@ signbit(x::Real) = x < 0 Return zero if `x==0` and ``x/|x|`` otherwise (i.e., ±1 for real `x`). """ -sign(x::Number) = x == 0 ? x/abs(one(x)) : x/abs(x) -sign(x::Real) = ifelse(x < 0, oftype(x,-1), ifelse(x > 0, one(x), x)) -sign(x::Unsigned) = ifelse(x > 0, one(x), x) +sign(x::Number) = x == 0 ? x/abs(oneunit(x)) : x/abs(x) +sign(x::Real) = ifelse(x < 0, oftype(one(x),-1), ifelse(x > 0, one(x), typeof(one(x))(x))) +sign(x::Unsigned) = ifelse(x > 0, one(x), oftype(one(x),0)) abs(x::Real) = ifelse(signbit(x), -x, x) """ @@ -132,12 +132,58 @@ zero{T<:Number}(::Type{T}) = convert(T,0) """ one(x) + one(T::type) + +Return a multiplicative identity for `x`: a value such that +`one(x)*x == x*one(x) == x`. Alternatively `one(T)` can +take a type `T`, in which case `one` returns a multiplicative +identity for any `x` of type `T`. + +If possible, `one(x)` returns a value of the same type as `x`, +and `one(T)` returns a value of type `T`. However, this may +not be the case for types representing dimensionful quantities +(e.g. time in days), since the multiplicative +identity must be dimensionless. In that case, `one(x)` +should return an identity value of the same precision +(and shape, for matrices) as `x`. + +If you want a quantity that is of the same type as `x`, or of type `T`, +even if `x` is dimensionful, use [`oneunit`](@ref) instead. +```jldoctest +julia> one(3.7) +1.0 + +julia> one(Int) +1 -Get the multiplicative identity element for the type of `x` (`x` can also specify the type -itself). For matrices, returns an identity matrix of the appropriate size and type. +julia> one(Dates.Day(1)) +1 +``` """ -one(x::Number) = oftype(x,1) one{T<:Number}(::Type{T}) = convert(T,1) +one{T<:Number}(x::T) = one(T) +# note that convert(T, 1) should throw an error if T is dimensionful, +# so this fallback definition should be okay. + +""" + oneunit(x::T) + oneunit(T::Type) + +Returns `T(one(x))`, where `T` is either the type of the argument or +(if a type is passed) the argument. This differs from [`one`](@ref) for +dimensionful quantities: `one` is dimensionless (a multiplicative identity) +while `oneunit` is dimensionful (of the same type as `x`, or of type `T`). + +```jldoctest +julia> oneunit(3.7) +1.0 + +julia> oneunit(Dates.Day) +1 day +``` +""" +oneunit{T}(x::T) = T(one(x)) +oneunit{T}(::Type{T}) = T(one(T)) _default_type(::Type{Number}) = Int diff --git a/base/random.jl b/base/random.jl index 1e38a43052d8b..ed7cd3174567e 100644 --- a/base/random.jl +++ b/base/random.jl @@ -459,7 +459,7 @@ function rand!{T<:Union{Float16, Float32}}(r::MersenneTwister, A::Array{T}, ::Ty A128[i] = mask128(u, T) end for i in 16*n128÷sizeof(T)+1:n - @inbounds A[i] = rand(r, T) + one(T) + @inbounds A[i] = rand(r, T) + oneunit(T) end A end @@ -523,10 +523,10 @@ rem_knuth{T<:Unsigned}(a::T, b::T) = b != 0 ? a % b : a # maximum multiple of k <= 2^bits(T) decremented by one, # that is 0xFFFF...FFFF if k = typemax(T) - typemin(T) with intentional underflow # see http://stackoverflow.com/questions/29182036/integer-arithmetic-add-1-to-uint-max-and-divide-by-n-without-overflow -maxmultiple{T<:Unsigned}(k::T) = (div(typemax(T) - k + one(k), k + (k == 0))*k + k - one(k))::T +maxmultiple{T<:Unsigned}(k::T) = (div(typemax(T) - k + oneunit(k), k + (k == 0))*k + k - oneunit(k))::T # maximum multiple of k within 1:2^32 or 1:2^64 decremented by one, depending on size -maxmultiplemix(k::UInt64) = if k >> 32 != 0; maxmultiple(k); else (div(0x0000000100000000, k + (k == 0))*k - one(k))::UInt64; end +maxmultiplemix(k::UInt64) = if k >> 32 != 0; maxmultiple(k); else (div(0x0000000100000000, k + (k == 0))*k - oneunit(k))::UInt64; end abstract RangeGenerator @@ -544,7 +544,7 @@ RangeGenerator{T<:Unsigned}(r::UnitRange{T}) = begin if isempty(r) throw(ArgumentError("range must be non-empty")) end - RangeGeneratorInt(first(r), last(r) - first(r) + one(T)) + RangeGeneratorInt(first(r), last(r) - first(r) + oneunit(T)) end # specialized versions diff --git a/base/range.jl b/base/range.jl index 6bd7b50fe91a7..628cfecb6cdfd 100644 --- a/base/range.jl +++ b/base/range.jl @@ -112,13 +112,13 @@ function steprange_last_empty{T<:Integer}(start::T, step, stop) # start - step, which leads to a range that looks very large instead # of empty. if step > zero(step) - last = start - one(stop-start) + last = start - oneunit(stop-start) else - last = start + one(stop-start) + last = start + oneunit(stop-start) end last end -# For types where x+one(x) may not be well-defined +# For types where x+oneunit(x) may not be well-defined steprange_last_empty(start, step, stop) = start - step steprem(start,stop,step) = (stop-start) % step @@ -134,10 +134,10 @@ UnitRange(start::T, stop::T) where T<:Real = UnitRange{T}(start, stop) unitrange_last(::Bool, stop::Bool) = stop unitrange_last{T<:Integer}(start::T, stop::T) = - ifelse(stop >= start, stop, convert(T,start-one(stop-start))) + ifelse(stop >= start, stop, convert(T,start-oneunit(stop-start))) unitrange_last{T}(start::T, stop::T) = ifelse(stop >= start, convert(T,start+floor(stop-start)), - convert(T,start-one(stop-start))) + convert(T,start-oneunit(stop-start))) """ Base.OneTo(n) @@ -388,7 +388,7 @@ let smallint = (Int === Int64 ? end first{T}(r::OrdinalRange{T}) = convert(T, r.start) -first{T}(r::OneTo{T}) = one(T) +first{T}(r::OneTo{T}) = oneunit(T) first(r::StepRangeLen) = unsafe_getindex(r, 1) first(r::LinSpace) = r.start @@ -425,11 +425,11 @@ start{T}(r::StepRangeLen{T}) = (unsafe_getindex(r, 1), 1) next{T}(r::StepRangeLen{T}, s) = s[1], (T(s[1]+r.step), s[2]+1) done{T}(r::StepRangeLen{T}, s) = s[2] > length(r) -start{T}(r::UnitRange{T}) = oftype(r.start + one(T), r.start) -next{T}(r::AbstractUnitRange{T}, i) = (convert(T, i), i + one(T)) -done{T}(r::AbstractUnitRange{T}, i) = i == oftype(i, r.stop) + one(T) +start{T}(r::UnitRange{T}) = oftype(r.start + oneunit(T), r.start) +next{T}(r::AbstractUnitRange{T}, i) = (convert(T, i), i + oneunit(T)) +done{T}(r::AbstractUnitRange{T}, i) = i == oftype(i, r.stop) + oneunit(T) -start{T}(r::OneTo{T}) = one(T) +start{T}(r::OneTo{T}) = oneunit(T) # some special cases to favor default Int type to avoid overflow let smallint = (Int === Int64 ? diff --git a/base/set.jl b/base/set.jl index 2e6fc6dd5b8ff..285a65e9f1af7 100644 --- a/base/set.jl +++ b/base/set.jl @@ -191,7 +191,7 @@ end allunique(::Set) = true -allunique{T}(r::Range{T}) = (step(r) != zero(T)) || (length(r) <= one(T)) +allunique{T}(r::Range{T}) = (step(r) != zero(T)) || (length(r) <= 1) function filter(f, s::Set) u = similar(s) diff --git a/base/sort.jl b/base/sort.jl index 19293811a2269..61bef81914c28 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -445,7 +445,7 @@ function sort!(v::AbstractVector; if n > 1 min, max = extrema(v) (diff, o1) = sub_with_overflow(max, min) - (rangelen, o2) = add_with_overflow(diff, one(diff)) + (rangelen, o2) = add_with_overflow(diff, oneunit(diff)) if !o1 && !o2 && rangelen < div(n,2) return sort_int_range!(v, rangelen, min) end @@ -534,7 +534,7 @@ function sortperm(v::AbstractVector; if n > 1 min, max = extrema(v) (diff, o1) = sub_with_overflow(max, min) - (rangelen, o2) = add_with_overflow(diff, one(diff)) + (rangelen, o2) = add_with_overflow(diff, oneunit(diff)) if !o1 && !o2 && rangelen < div(n,2) return sortperm_int_range(v, rangelen, min) end @@ -676,7 +676,7 @@ function slicetypeof{T,N}(A::AbstractArray{T,N}, i1, i2) SubArray{T,1,typeof(A),typeof(I),fast} end slice_dummy(S::Slice) = S -slice_dummy{T}(::AbstractUnitRange{T}) = one(T) +slice_dummy{T}(::AbstractUnitRange{T}) = oneunit(T) ## fast clever sorting for floats ## diff --git a/base/sparse/higherorderfns.jl b/base/sparse/higherorderfns.jl index acffdd0048efb..ea947b9336eba 100644 --- a/base/sparse/higherorderfns.jl +++ b/base/sparse/higherorderfns.jl @@ -248,14 +248,14 @@ function _map_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B::Spar if Ai == Bi Ai == rowsentinelA && break # column complete Cx, Ci::indtype(C) = f(storedvals(A)[Ak], storedvals(B)[Bk]), Ai - Ak += one(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA - Bk += one(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB + Ak += oneunit(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA + Bk += oneunit(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB elseif Ai < Bi Cx, Ci = f(storedvals(A)[Ak], zero(eltype(B))), Ai - Ak += one(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA + Ak += oneunit(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA else # Bi < Ai Cx, Ci = f(zero(eltype(A)), storedvals(B)[Bk]), Bi - Bk += one(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB + Bk += oneunit(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB end # NOTE: The ordering of the conditional chain above impacts which matrices this # method performs best for. In the map situation (arguments have same shape, and @@ -293,14 +293,14 @@ function _map_notzeropres!{Tf}(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVec if Ai == Bi Ai == rowsentinelA && break # column complete Cx, Ci::indtype(C) = f(storedvals(A)[Ak], storedvals(B)[Bk]), Ai - Ak += one(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA - Bk += one(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB + Ak += oneunit(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA + Bk += oneunit(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB elseif Ai < Bi Cx, Ci = f(storedvals(A)[Ak], zero(eltype(B))), Ai - Ak += one(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA + Ak += oneunit(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA else # Bi < Ai Cx, Ci = f(zero(eltype(A)), storedvals(B)[Bk]), Bi - Bk += one(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB + Bk += oneunit(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB end Cx != fillvalue && (storedvals(C)[jo + Ci] = Cx) end @@ -396,7 +396,7 @@ end # @inline _gatherargs(activerows, ks, As) = ( # _gatherarg(first(activerows), first(ks), first(As)), # _gatherargs(tail(activerows), tail(ks), tail(As))...) -# @inline _updateind(isactiverow, k) = isactiverow ? (k + one(k)) : k +# @inline _updateind(isactiverow, k) = isactiverow ? (k + oneunit(k)) : k # @inline _updateind_all(::Tuple{}, ::Tuple{}) = () # @inline _updateind_all(activerows, ks) = ( # _updateind(first(activerows), first(ks)), @@ -410,7 +410,7 @@ end @inline function _fusedupdate(rowsentinel, activerow, row, k, stopk, A) # returns (val, nextk, nextrow) if row == activerow - nextk = k + one(k) + nextk = k + oneunit(k) (storedvals(A)[k], nextk, (nextk < stopk ? storedinds(A)[nextk] : oftype(row, rowsentinel))) else (zero(eltype(A)), k, row) @@ -543,17 +543,17 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B if Ai != Bi if Ai < Bi Cx, Ci = f(storedvals(A)[Ak], zero(eltype(B))), Ai - Ak += one(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA + Ak += oneunit(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA else # Ai > Bi Cx, Ci = f(zero(eltype(A)), storedvals(B)[Bk]), Bi - Bk += one(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB + Bk += oneunit(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB end elseif #= Ai == Bi && =# Ai == rowsentinelA break # column complete else #= Ai == Bi != rowsentinel =# Cx, Ci::indtype(C) = f(storedvals(A)[Ak], storedvals(B)[Bk]), Ai - Ak += one(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA - Bk += one(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB + Ak += oneunit(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA + Bk += oneunit(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB end # NOTE: The ordering of the conditional chain above impacts which matrices # this method perform best for. In contrast to the map situation (arguments @@ -592,7 +592,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B storedvals(C)[Ck] = Cx Ck += 1 end - Bk += one(Bk) + Bk += oneunit(Bk) end else # A's jth column is nonempty and f(Ax, zero(eltype(B))) is not zero, so @@ -601,7 +601,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B for Ci::indtype(C) in 1:numrows(C) if Bi == Ci Cx = f(Ax, storedvals(B)[Bk]) - Bk += one(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB + Bk += oneunit(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB else Cx = fvAzB end @@ -633,7 +633,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B storedvals(C)[Ck] = Cx Ck += 1 end - Ak += one(Ak) + Ak += oneunit(Ak) end else # B's jth column is nonempty and f(zero(eltype(A)), Bx) is not zero, so @@ -642,7 +642,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B for Ci::indtype(C) in 1:numrows(C) if Ai == Ci Cx = f(storedvals(A)[Ak], Bx) - Ak += one(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA + Ak += oneunit(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA else Cx = fzAvB end @@ -678,16 +678,16 @@ function _broadcast_notzeropres!{Tf}(f::Tf, fillvalue, C::SparseVecOrMat, A::Spa while true if Ai < Bi Cx, Ci = f(storedvals(A)[Ak], zero(eltype(B))), Ai - Ak += one(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA + Ak += oneunit(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA elseif Ai > Bi Cx, Ci = f(zero(eltype(A)), storedvals(B)[Bk]), Bi - Bk += one(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB + Bk += oneunit(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB elseif #= Ai == Bi && =# Ai == rowsentinelA break # column complete else #= Ai == Bi != rowsentinel =# Cx, Ci::indtype(C) = f(storedvals(A)[Ak], storedvals(B)[Bk]), Ai - Ak += one(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA - Bk += one(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB + Ak += oneunit(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA + Bk += oneunit(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB end Cx != fillvalue && (storedvals(C)[jo + Ci] = Cx) end @@ -703,14 +703,14 @@ function _broadcast_notzeropres!{Tf}(f::Tf, fillvalue, C::SparseVecOrMat, A::Spa while Bk < stopBk Cx = f(Ax, storedvals(B)[Bk]) Cx != fillvalue && (storedvals(C)[jo + storedinds(B)[Bk]] = Cx) - Bk += one(Bk) + Bk += oneunit(Bk) end else Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB for Ci::indtype(C) in 1:numrows(C) if Bi == Ci Cx = f(Ax, storedvals(B)[Bk]) - Bk += one(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB + Bk += oneunit(Bk); Bi = Bk < stopBk ? storedinds(B)[Bk] : rowsentinelB else Cx = fvAzB end @@ -728,14 +728,14 @@ function _broadcast_notzeropres!{Tf}(f::Tf, fillvalue, C::SparseVecOrMat, A::Spa while Ak < stopAk Cx = f(storedvals(A)[Ak], Bx) Cx != fillvalue && (storedvals(C)[jo + storedinds(A)[Ak]] = Cx) - Ak += one(Ak) + Ak += oneunit(Ak) end else Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA for Ci::indtype(C) in 1:numrows(C) if Ai == Ci Cx = f(storedvals(A)[Ak], Bx) - Ak += one(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA + Ak += oneunit(Ak); Ai = Ak < stopAk ? storedinds(A)[Ak] : rowsentinelA else Cx = fzAvB end @@ -905,7 +905,7 @@ end # @inline _gatherbcargs(activerows, defargs, ks, As) = ( # _gatherbcarg(first(activerows), first(defargs), first(ks), first(As)), # _gatherbcargs(tail(activerows), tail(defargs), tail(ks), tail(As))...) -# @inline _updateind(isactiverow, k) = isactiverow ? (k + one(k)) : k +# @inline _updateind(isactiverow, k) = isactiverow ? (k + oneunit(k)) : k # @inline _updateind_all(::Tuple{}, ::Tuple{}) = () # @inline _updateind_all(activerows, ks) = ( # _updateind(first(activerows), first(ks)), @@ -919,7 +919,7 @@ end @inline function _fusedupdatebc(rowsentinel, activerow, row, defarg, k, stopk, A) # returns (val, nextk, nextrow) if row == activerow - nextk = k + one(k) + nextk = k + oneunit(k) (storedvals(A)[k], nextk, (nextk < stopk ? storedinds(A)[nextk] : oftype(row, rowsentinel))) else (defarg, k, row) diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index 1345c9fa848e9..477757b6f280b 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -6,14 +6,14 @@ import Base.LinAlg: checksquare # Convert from 1-based to 0-based indices function decrement!{T<:Integer}(A::AbstractArray{T}) - for i in 1:length(A); A[i] -= one(T) end + for i in 1:length(A); A[i] -= oneunit(T) end A end decrement{T<:Integer}(A::AbstractArray{T}) = decrement!(copy(A)) # Convert from 0-based to 1-based indices function increment!{T<:Integer}(A::AbstractArray{T}) - for i in 1:length(A); A[i] += one(T) end + for i in 1:length(A); A[i] += oneunit(T) end A end increment{T<:Integer}(A::AbstractArray{T}) = increment!(copy(A)) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index 73a1592adfc02..58e8371e86b96 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -1380,7 +1380,7 @@ if not specified. `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, one(T), m, n) +speye(T::Type, m::Integer, n::Integer) = speye_scaled(T, oneunit(T), m, n) function one{T}(S::SparseMatrixCSC{T}) m,n = size(S) diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index ec71d9f0f8bdc..8a4ea93c4e82a 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -1334,13 +1334,13 @@ function LinAlg.axpy!(a::Number, x::AbstractSparseVector, y::StridedVector) nzval = nonzeros(x) m = length(nzind) - if a == one(a) + if a == oneunit(a) for i = 1:m @inbounds ii = nzind[i] @inbounds v = nzval[i] y[ii] += v end - elseif a == -one(a) + elseif a == -oneunit(a) for i = 1:m @inbounds ii = nzind[i] @inbounds v = nzval[i] diff --git a/base/special/gamma.jl b/base/special/gamma.jl index 48f925885c428..f69e548f03db3 100644 --- a/base/special/gamma.jl +++ b/base/special/gamma.jl @@ -29,7 +29,7 @@ lgamma_r(x::Number) = lgamma(x), 1 # lgamma does not take abs for non-real x Compute the logarithmic factorial of `x` """ -lfact(x::Real) = (x<=1 ? zero(float(x)) : lgamma(x+one(x))) +lfact(x::Real) = (x<=1 ? zero(float(x)) : lgamma(x+oneunit(x))) """ lgamma(x) diff --git a/base/statistics.jl b/base/statistics.jl index a2c47f2481d1a..8e03f185c0c55 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -389,7 +389,7 @@ function cov2cor!{T}(C::AbstractMatrix{T}, xsd::AbstractArray) for i = 1:j-1 C[i,j] = C[j,i] end - C[j,j] = one(T) + C[j,j] = oneunit(T) for i = j+1:nx C[i,j] = clamp(C[i,j] / (xsd[i] * xsd[j]), -1, 1) end diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index 684dbe54cb51d..4cdd7ac568bc4 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -564,7 +564,8 @@ optimize the body of the loop. There are several possible fixes: * Initialize `x` with `x = 1.0` * Declare the type of `x`: `x::Float64 = 1` - * Use an explicit conversion: `x = one(T)` + * Use an explicit conversion: `x = oneunit(T)` + * Initialize with the first loop iteration, to `x = 1/bar()`, then loop `for i = 2:10` ## [Separate kernel functions (aka, function barriers)](@id kernal-functions) diff --git a/doc/src/manual/style-guide.md b/doc/src/manual/style-guide.md index 3360b1ffab02d..e4063f58e2f3b 100644 --- a/doc/src/manual/style-guide.md +++ b/doc/src/manual/style-guide.md @@ -42,20 +42,20 @@ For example, consider the following definitions of a function `addone` that retu argument: ```julia -addone(x::Int) = x + 1 # works only for Int -addone(x::Integer) = x + one(x) # any integer type -addone(x::Number) = x + one(x) # any numeric type -addone(x) = x + one(x) # any type supporting + and one +addone(x::Int) = x + 1 # works only for Int +addone(x::Integer) = x + oneunit(x) # any integer type +addone(x::Number) = x + oneunit(x) # any numeric type +addone(x) = x + oneunit(x) # any type supporting + and oneunit ``` -The last definition of `addone` handles any type supporting [`one()`](@ref) (which returns 1 in +The last definition of `addone` handles any type supporting [`oneunit`](@ref) (which returns 1 in the same type as `x`, which avoids unwanted type promotion) and the [`+`](@ref) function with those arguments. The key thing to realize is that there is *no performance penalty* to defining -*only* the general `addone(x) = x + one(x)`, because Julia will automatically compile specialized +*only* the general `addone(x) = x + oneunit(x)`, because Julia will automatically compile specialized versions as needed. For example, the first time you call `addone(12)`, Julia will automatically -compile a specialized `addone` function for `x::Int` arguments, with the call to [`one()`](@ref) +compile a specialized `addone` function for `x::Int` arguments, with the call to `oneunit` replaced by its inlined value `1`. Therefore, the first three definitions of `addone` above are -completely redundant. +completely redundant with the fourth definition. ## Handle excess argument diversity in the caller diff --git a/doc/src/stdlib/numbers.md b/doc/src/stdlib/numbers.md index 87afb1c36e3bc..36ee7e5634d2f 100644 --- a/doc/src/stdlib/numbers.md +++ b/doc/src/stdlib/numbers.md @@ -50,6 +50,7 @@ Base.bytes2hex ```@docs Base.one +Base.oneunit Base.zero Base.pi Base.im