Skip to content

Commit

Permalink
general improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher Doris committed Oct 2, 2019
1 parent 72512fc commit 91569e4
Show file tree
Hide file tree
Showing 15 changed files with 396 additions and 52 deletions.
6 changes: 6 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ Requires = "ae029012-a4dd-5104-9daa-d747884805df"

[compat]
julia = "1.0"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test"]
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

A [logarithmic number system](https://en.wikipedia.org/wiki/Logarithmic_number_system) for Julia.

Provides two subtypes of `Real`: the unsigned `ULogarithmic`, representing a positive number in log-space; and signed `Logarithmic` which additionally has a sign bit.
Provides the types `ULogarithmic`, `Logarithmic` and `CLogarithmic` for representing non-negative real numbers, real numbers and complex numbers in log-space.

This is useful when numbers are too big or small to fit accurately into a `Float64` and you only really care about magnitude.

Expand Down Expand Up @@ -38,18 +38,19 @@ julia> log(x)

## Documentation

Two main types are exported:
* Type `ULogarithmic{T}`, which represents a positive real number by its logarithm of type `T`.
* Type `Logarithmic{T}` (signed), which represents a real number by its absolute value as a `ULogarithmic{T}` and a sign bit.
Three main types are exported:
* Type `ULogarithmic{T}`, which represents a non-negative real number by its logarithm of type `T`.
* Type `Logarithmic{T}`, which represents a real number by its absolute value as a `ULogarithmic{T}` and a sign bit.
* Type `CLogarithmic{T}`, which represents a complex number by its absolute value as a `ULogarithmic{T}` and an angle of type `T`.

Also exports type aliases `ULogFloat64`, `LogFloat64`, `ULogFloat32`, `LogFloat32`, `ULogFloat16`, `LogFloat16`, `ULogBigFloat`, `LogBigFloat`.
Also exports type aliases `ULogFloat64`, `LogFloat64`, `CLogFloat64`, `ULogFloat32`, `LogFloat32`, `CLogFloat32`, `ULogFloat16`, `LogFloat16`, `CLogFloat16`, `ULogBigFloat`, `LogBigFloat`, `CLogBigFloat`.

Features:
* `ULogarithmic(x)` and `Logarithmic(x)` represent the number `x`.
* `exp(ULogarithmic, x)` and `exp(Logarithmic, x)` represent `exp(x)` (and `x` can be huge).
* `ULogarithmic(x)` (and `Logarithmic(x)`, etc.) represents the number `x`.
* `exp(ULogarithmic, x)` represents `exp(x)` (and `x` can be huge).
* Arithmetic: `+`, `-`, `*`, `/`, `^`, `inv`, `log`, `prod`, `sum`.
* Comparisons: equality, ordering, `cmp`, `isless`.
* Random: `rand(ULogarithmic)` and `rand(Logarithmic)` produces a random number in the unit interval.
* Random: `rand(ULogarithmic)` is a random number in the unit interval.
* Other functions: `float`, `big`, `unsigned` (converts `ULogarithmic` to `Logarithmic`), `signed` (vice versa), `widen`, `typemin`, `typemax`, `zero`, `one`, `iszero`, `isone`, `isinf`, `isfinite`, `isnan`, `sign`, `signbit`, `abs`, `nextfloat`, `prevfloat`, `write`, `read`.

## Interoperability with other packages
Expand Down
15 changes: 12 additions & 3 deletions src/LogarithmicNumbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,21 @@ module LogarithmicNumbers

using Requires, Random

import Base: exp, log, *, /, ^, inv, +, -, prod, sum, show, write, read, float, big, unsigned, signed, widen, typemin, typemax, zero, one, iszero, isone, isinf, isfinite, isnan, sign, signbit, abs, ==, <, , cmp, isless, nextfloat, prevfloat, rand, promote_rule
import Base:
exp, log, *, /, ^, inv, +, -, prod, sum, angle, show,
write, read, float, big, unsigned, signed, widen,
typemin, typemax, zero, one, iszero, isone, isinf,
isfinite, isnan, sign, signbit, abs, ==, isequal, <, ,
cmp, isless, nextfloat, prevfloat, rand, promote_rule,
conj, real, imag

export AbstractLogarithmic, ULogarithmic, Logarithmic
export ULogarithmic, Logarithmic, CLogarithmic

include("types.jl")
include("constructors.jl")
include("ulogarithmic.jl")
include("logarithmic.jl")
include("clogarithmic.jl")
include("promotion.jl")
include("arithmetic.jl")
include("random.jl")
Expand All @@ -25,10 +32,12 @@ include("init.jl")
for T in (Float64, Float32, Float16, BigFloat)
ULogT = Symbol(:ULog, T)
LogT = Symbol(:Log, T)
CLogT = Symbol(:CLog, T)
@eval begin
const $(ULogT) = $(ULogarithmic{T})
const $(LogT) = $(Logarithmic{T})
export $(ULogT), $(LogT)
const $(CLogT) = $(CLogarithmic{T})
export $(ULogT), $(LogT), $(CLogT)
end
end

Expand Down
50 changes: 48 additions & 2 deletions src/arithmetic.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
exp(x::ALog) = uexp(x)
# generic

exp(x::AnyLog) = uexp(x)

# ULogarithmic

log(x::ULogarithmic) = x.log
*(x::ULogarithmic{T}, y::ULogarithmic{T}, rest::ULogarithmic{T}...) where {T} = uexp(T, +(log.((x, y, rest...))...))
Expand All @@ -8,13 +12,15 @@ log(x::ULogarithmic) = x.log
inv(x::ULogarithmic{T}) where {T} = uexp(T, -x.log)
# +(x::ULogarithmic, y::ULogarithmic) = x.log ≥ y.log ? x * ULogarithmic(1 + float(y/x)) : y * ULogarithmic(float(x/y) + 1)
+(x::ULogarithmic{T}, y::ULogarithmic{T}, rest::ULogarithmic{T}...) where {T} = _add(x, y, rest...)
-(x::ULogarithmic{T}, y::ULogarithmic{T}) where {T} = (xlog=x.log; ylog=y.log; xlog<ylog && error("difference is negative"); uexp(xlog - -log(1 - exp(-float(xlog-ylog)))))
-(x::ULogarithmic{T}, y::ULogarithmic{T}) where {T} = (xlog=x.log; ylog=y.log; xlog<ylog && throw(DomainError((x,y), "difference is negative")); uexp(xlog - -log(1 - exp(-float(==(xlog, ylog) ? zero(xlog-ylog) : xlog-ylog)))))

@inline _add(xs::ULogarithmic{T}...) where {T} = (xlogs=log.(xs); maxlog=max(xlogs...); isinf(maxlog) ? uexp(maxlog)::typeof(uexp(maxlog + log(+(exp.(float.(xlogs.-maxlog))...)))) : uexp(maxlog + log(+(exp.(.-float.(maxlog.-xlogs))...))))

prod(xs::AbstractArray{<:ULogarithmic}) = uexp(sum(log.(xs)))
sum(xs::AbstractArray{<:ULogarithmic}) = (xlogs=log.(xs); maxlog=maximum(xlogs); isinf(maxlog) ? uexp(maxlog)::typeof(uexp(maxlog + log(sum(exp.(.-float.(maxlog.-xlogs)))))) : uexp(maxlog + log(sum(exp.(.-float.(maxlog.-xlogs))))))

# Logarithmic

-(x::Logarithmic) = Logarithmic(x.abs, !x.signbit)
log(x::Logarithmic) = (x.signbit && !iszero(x) && throw(DomainError(x)); log(x.abs))
*(x::Logarithmic{T}, y::Logarithmic{T}) where {T} = Logarithmic{T}(x.abs * y.abs, x.signbit y.signbit)
Expand All @@ -25,3 +31,43 @@ inv(x::Logarithmic{T}) where {T} = Logarithmic{T}(inv(x.abs), x.signbit)
+(x::Logarithmic{T}, y::Logarithmic{T}) where {T} = x.signbit==y.signbit ? Logarithmic(x.abs + y.abs, x.signbit) : x.abs y.abs ? Logarithmic(x.abs - y.abs, x.signbit) : Logarithmic(y.abs - x.abs, y.signbit)
-(x::Logarithmic{T}, y::Logarithmic{T}) where {T} = x.signbit==y.signbit ? x.abs y.abs ? Logarithmic(x.abs - y.abs, x.signbit) : Logarithmic(y.abs - x.abs, !y.signbit) : Logarithmic(x.abs + y.abs, x.signbit)

# CLogarithmic

log(x::CLogarithmic) = Complex(x.abs.log, x.angle)
conj(x::CLogarithmic) = CLogarithmic(x.abs, -x.angle)
*(x::CLogarithmic{T}, y::CLogarithmic{T}) where {T} =
CLogarithmic{T}(x.abs * y.abs, x.angle + y.angle)
/(x::CLogarithmic{T}, y::CLogarithmic{T}) where {T} =
CLogarithmic{T}(x.abs / y.abs, x.angle - y.angle)
^(x::CLogarithmic, n::Integer) = CLogarithmic(x.abs^n, x.angle*n)
^(x::CLogarithmic, n::Real) = CLogarithmic(x.abs^n, x.angle*n)
inv(x::CLogarithmic) = CLogarithmic(inv(x.abs), -x.angle)
+(x::CLogarithmic{T}, y::CLogarithmic{T}) where {T} =
if isinf(x) && isinf(y) && x.angle y.angle
t = exp(zero(Complex{T}))
x * t
elseif iszero(x) && iszero(y)
t = exp(zero(Complex{T}))
x * t
elseif x.abs y.abs
t = exp(Complex(y.abs.log-x.abs.log,y.angle-x.angle))
t += one(t)
x * t
else
t = exp(Complex(x.abs.log-y.abs.log,x.angle-y.angle))
t += one(t)
t * y
end
-(x::CLogarithmic{T}, y::CLogarithmic{T}) where {T} =
if iszero(x) && iszero(y)
t = exp(zero(Complex{T}))
x * t
elseif x.abs y.abs
t = exp(Complex(y.abs.log-x.abs.log,y.angle-x.angle))
t = one(t) - t
x * t
else
t = exp(Complex(x.abs.log-y.abs.log,x.angle-y.angle))
t = t - one(t)
t * y
end
31 changes: 31 additions & 0 deletions src/clogarithmic.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# conversion
float(x::CLogarithmic) = Complex(exp(Complex(float(x.abs.log), float(x.angle))))
(::Type{T})(x::CLogarithmic) where {T<:AbstractFloat} = (y=float(x.abs); T(iszero(x.angle) ? y : x.angleπ ? -y : throw(DomainError(x))))
(::Type{T})(x::CLogarithmic) where {T<:Complex} = T(exp(Complex(x.abs.log, x.angle)))
big(x::CLogarithmic) = CLogarithmic(big(x.abs), big(x.angle))

# type functions
widen(::Type{CLogarithmic{T}}) where {T} = CLogarithmic{widen(T)}
big(::Type{CLogarithmic{T}}) where {T} = CLogarithmic{big(T)}

# special values
zero(::Type{CLogarithmic{T}}) where {T} = CLogarithmic(zero(ULogarithmic{T}))
one(::Type{CLogarithmic{T}}) where {T} = CLogarithmic(one(ULogarithmic{T}))

# predicates
iszero(x::CLogarithmic) = iszero(x.abs)
isone(x::CLogarithmic) = isone(x.abs) && iszero(x.angle)
isinf(x::CLogarithmic) = isinf(x.abs)
isfinite(x::CLogarithmic) = isfinite(x.abs)
isnan(x::CLogarithmic) = isnan(x.abs)

# sign
sign(x::CLogarithmic{T}) where {T} = iszero(x) ? zero(x) : CLogarithmic{T}(uexp(T,0), x.angle)
abs(x::CLogarithmic) = x.abs
angle(x::CLogarithmic) = x.angle
real(x::CLogarithmic) = x.abs * cos(x.angle)
imag(x::CLogarithmic) = x.abs * sin(x.angle)

# ordering
(==)(x::CLogarithmic, y::CLogarithmic) = x.abs==y.abs && x.angle==y.angle
isequal(x::CLogarithmic, y::CLogarithmic) = isequal(x.abs, y.abs) && isequal(x.angle, y.angle)
69 changes: 55 additions & 14 deletions src/constructors.jl
Original file line number Diff line number Diff line change
@@ -1,37 +1,78 @@
# construct by exponentiation
"""
exp(T<:AbstractLogarithmic, x)
exp(T, x)
The number `exp(x)` represented as a `T`.
"""
exp(::Type{E} where {E<:(AbstractLogarithmic{T} where {T})}, x::Real)
exp(::Type{T} where {T<:AnyLog}, x::Real)

exp(::Type{ULogarithmic{T}}, x::Real) where {T<:Real} = exp(ULogarithmic{T}, convert(T, x))
exp(::Type{ULogarithmic}, x::T) where {T<:Real} = exp(ULogarithmic{T}, x)
exp(::Type{ULogarithmic{T}}, x::Real) where {T<:Real} =
exp(ULogarithmic{T}, convert(T, x))

exp(::Type{Logarithmic{T}}, x::Real) where {T<:Real} = Logarithmic{T}(exp(ULogarithmic{T}, x))
exp(::Type{Logarithmic}, x::T) where {T<:Real} = Logarithmic{T}(exp(ULogarithmic{T}, x))
exp(::Type{ULogarithmic}, x::T) where {T<:Real} =
exp(ULogarithmic{T}, x)

exp(::Type{AbstractLogarithmic{T}}, x::Real) where {T<:Real} = exp(ULogarithmic{T}, x)
exp(::Type{AbstractLogarithmic}, x::Real) = exp(ULogarithmic, x)
exp(::Type{Logarithmic{T}}, x::Real) where {T<:Real} =
Logarithmic{T}(exp(ULogarithmic{T}, x))

exp(::Type{Logarithmic}, x::T) where {T<:Real} =
exp(Logarithmic{T}, x)

exp(::Type{CLogarithmic{T}}, x::Union{Real,Complex}) where {T<:Real} =
CLogarithmic{T}(exp(ULogarithmic{T}, real(x)), imag(x))

exp(::Type{CLogarithmic}, x::T) where {T<:Real} =
exp(CLogarithmic{T}, x)

exp(::Type{CLogarithmic}, x::Complex{T}) where {T<:Real} =
exp(CLogarithmic{T}, x)

# convenience
uexp(x) = exp(ULogarithmic, x)
uexp(T,x) = exp(ULogarithmic{T}, x)

# convert to ULogarithmic
ULogarithmic{T}(x::Real) where {T<:Real} = exp(ULogarithmic{T}, log(x))

ULogarithmic{T}(x::ULogarithmic{T}) where {T<:Real} = x

ULogarithmic(x::Real) = exp(ULogarithmic, log(x))

AbstractLogarithmic{T}(x::Real) where {T<:Real} = ULogarithmic{T}(x)
AbstractLogarithmic(x::T) where {T<:Real} = ULogarithmic(x)
ULogarithmic(x::ULogarithmic) = x

# convert to Logarithmic
Logarithmic{T}(x::Real) where {T<:Real} = Logarithmic{T}(ULogarithmic{T}(abs(x)), signbit(x))

Logarithmic{T}(x::Real) where {T<:Real} =
Logarithmic{T}(ULogarithmic{T}(abs(x)), signbit(x))

Logarithmic{T}(x::Logarithmic{T}) where {T<:Real} = x
Logarithmic{T}(abs::ULogarithmic, signbit::Bool=false) where {T<:Real} = Logarithmic{T}(ULogarithmic{T},(abs), signbit)

Logarithmic(x::Real) where {T<:Real} = Logarithmic(ULogarithmic(abs(x)), signbit(x))
Logarithmic(abs::ULogarithmic{T}, signbit::Bool=false) where {T<:Real} = Logarithmic{T}(abs, signbit)
Logarithmic{T}(abs::ULogarithmic, signbit::Bool=false) where {T<:Real} =
Logarithmic{T}(ULogarithmic{T}(abs), signbit)

Logarithmic(x::Real) =
Logarithmic(ULogarithmic(abs(x)), signbit(x))

Logarithmic(abs::ULogarithmic{T}, signbit::Bool=false) where {T<:Real} =
Logarithmic{T}(abs, signbit)

Logarithmic(x::Logarithmic) = x

# convert to CLogarithmic

CLogarithmic{T}(x::Union{Real,Complex}) where {T<:Real} =
CLogarithmic{T}(ULogarithmic{T}(abs(x)), convert(T, angle(x)))

CLogarithmic{T}(x::CLogarithmic{T}) where {T<:Real} = x

CLogarithmic{T}(x::CLogarithmic) where {T<:Real} =
CLogarithmic{T}(x.abs, x.angle)

CLogarithmic{T}(abs::ULogarithmic, angle::Real=zero(T)) where {T<:Real} =
CLogarithmic{T}(ULogarithmic{T}(abs), convert(T, angle))

CLogarithmic(x::Union{Real,Complex}) =
CLogarithmic(ULogarithmic(abs(x)), angle(x))

CLogarithmic(abs::ULogarithmic{T}, angle::A=zero(T)) where {T<:Real, A<:Real} =
CLogarithmic{promote_type(T,A)}(abs, angle)
6 changes: 3 additions & 3 deletions src/distributions.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import .Distributions

Distributions.cdf(::Type{E}, args...; opts...) where {E<:ALog} = exp(E, Distributions.logcdf(args...; opts...))
Distributions.ccdf(::Type{E}, args...; opts...) where {E<:ALog} = exp(E, Distributions.logccdf(args...; opts...))
Distributions.pdf(::Type{E}, args...; opts...) where {E<:ALog} = exp(E, Distributions.logpdf(args...; opts...))
Distributions.cdf(::Type{E}, args...; opts...) where {E<:AnyLog} = exp(E, Distributions.logcdf(args...; opts...))
Distributions.ccdf(::Type{E}, args...; opts...) where {E<:AnyLog} = exp(E, Distributions.logccdf(args...; opts...))
Distributions.pdf(::Type{E}, args...; opts...) where {E<:AnyLog} = exp(E, Distributions.logpdf(args...; opts...))
10 changes: 9 additions & 1 deletion src/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,16 @@ function show(io::IO, x::Logarithmic)
show(io, x.abs)
end

function show(io::IO, x::CLogarithmic)
print(io, "exp(")
show(io, log(x))
print(io, ")")
end

write(io::IO, x::ULogarithmic) = write(io, x.log)
write(io::IO, x::Logarithmic) = write(io, x.abs, x.signbit)
write(io::IO, x::CLogarithmic) = write(io, x.abs, x.angle)

read(io::IO, ::Type{ULogarithmic{T}}) where {T} = uexp(T, read(io, T))
read(io::IO, ::Type{Logarithmic{T}}) where {T} = Logarithmic{T}(read(io, ULogarithmic{T}), read(io, Bool))
read(io::IO, ::Type{Logarithmic{T}}) where {T} = Logarithmic{T}(read(io, ULogarithmic{T}), read(io, Bool))
read(io::IO, ::Type{CLogarithmic{T}}) where {T} = CLogarithmic{T}(read(io, ULogarithmic{T}), read(io, T))
4 changes: 3 additions & 1 deletion src/logarithmic.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# conversion
float(x::Logarithmic) = AbstractFloat(x)
(::Type{T})(x::Logarithmic) where {T<:AbstractFloat} = (y=float(x.abs); T(ifelse(x.signbit, -y, y)))
big(x::Logarithmic) = Logarithmic(big(x.abs), x.signbit)
unsigned(x::Logarithmic) = (x.signbit && !iszero(x) && throw(DomainError(x)); x.abs)
Expand Down Expand Up @@ -26,10 +27,11 @@ isnan(x::Logarithmic) = isnan(x.abs)
# sign
sign(x::Logarithmic) = (s=sign(x.abs); ifelse(x.signbit, -s, s))
signbit(x::Logarithmic) = x.signbit
abs(x::Logarithmic) = Logarithmic(x.abs)
abs(x::Logarithmic) = x.abs

# ordering
(==)(x::Logarithmic, y::Logarithmic) = (iszero(x) && iszero(y)) || (x.abs==y.abs && x.signbit==y.signbit)
isequal(x::Logarithmic, y::Logarithmic) = isequal(x.abs, y.abs) && isequal(x.signbit, y.signbit)
<(x::Logarithmic, y::Logarithmic) = x.signbit ? y.signbit ? (y.abs < x.abs) : !(iszero(x) && iszero(y)) : y.signbit ? (false) : (x.abs < y.abs)
(x::Logarithmic, y::Logarithmic) = x.signbit ? y.signbit ? (y.abs x.abs) : true : y.signbit ? (iszero(x) && iszero(y)) : (x.abs y.abs)
isless(x::Logarithmic, y::Logarithmic) = x.signbit ? y.signbit ? isless(y.abs,x.abs) : true : y.signbit ? false : isless(x.abs,y.abs)
Expand Down
47 changes: 41 additions & 6 deletions src/promotion.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,41 @@
promote_rule(::Type{ULogarithmic{T}}, ::Type{ULogarithmic{R}}) where {T,R} = ULogarithmic{promote_type(T,R)}
promote_rule(::Type{ULogarithmic{T}}, ::Type{Logarithmic{R}}) where {T,R} = Logarithmic{promote_type(T,R)}
promote_rule(::Type{Logarithmic{T}}, ::Type{Logarithmic{R}}) where {T,R} = Logarithmic{promote_type(T,R)}
promote_rule(::Type{Logarithmic{T}}, ::Type{ULogarithmic{R}}) where {T,R} = Logarithmic{promote_type(T,R)}
promote_rule(::Type{ULogarithmic{T}}, ::Type{R}) where {T,R<:Real} = try ULogarithmic{promote_type(T,typeof(log(one(R))))}; catch; Union{}; end
promote_rule(::Type{Logarithmic{T}}, ::Type{R}) where {T,R<:Real} = try ULogarithmic{promote_type(T,typeof(log(one(R))))}; catch; Union{}; end
atypes = (ULogarithmic, Logarithmic, CLogarithmic)

# logarithmic + logarithmic

for (i,A) in enumerate(atypes)
for (j,B) in enumerate(atypes)
C = i<j ? B : A
@eval promote_rule(::Type{$A}, ::Type{$B}) = $C
@eval promote_rule(::Type{$A}, ::Type{$B{T}}) where {T} = $C{T}
@eval promote_rule(::Type{$A{T}}, ::Type{$B}) where {T} = $C{T}
@eval promote_rule(::Type{$A{S}}, ::Type{$B{T}}) where {S,T} =
$C{promote_type(S,T)}
end
end

# logarithmic + real

# generated for type-stability
@generated promote_rule(::Type{ULogarithmic}, ::Type{R}) where {R<:Real} =
try
:($(typeof(ULogarithmic(one(R)))))
catch
:(Union{})
end

promote_rule(::Type{A}, ::Type{R}) where {A<:AnyLog, R<:Real} =
promote_type(A, promote_type(ULogarithmic, R))

# logarithmic + complex
# only CLogarithmic+Complex is promoted, so that Logarithmic+Complex is promoted to Complex{Logarithmic}

# generated for type-stability
@generated promote_rule(::Type{CLogarithmic}, ::Type{C}) where {C<:Complex} =
try
:($(typeof(CLogarithmic(one(C)))))
catch
:(Union{})
end

promote_rule(::Type{CLogarithmic{T}}, ::Type{C}) where {T, C<:Complex} =
promote_type(CLogarithmic{T}, promote_type(CLogarithmic, C))
9 changes: 7 additions & 2 deletions src/random.jl
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
rand(rng::AbstractRNG, ::Random.SamplerType{E}) where {T<:AbstractFloat, E<:AbstractLogarithmic{T}} = exp(E, -randexp(rng, T))
rand(rng::AbstractRNG, ::Random.SamplerType{E}) where {E<:ALog} = exp(E, -randexp(rng))
rand(rng::AbstractRNG, ::Random.SamplerType{E}) where {T<:AbstractFloat, E<:RealLog{T}} =
exp(E, -randexp(rng, T))
rand(rng::AbstractRNG, ::Random.SamplerType{E}) where {E<:RealLog} =
exp(E, -randexp(rng))

# todo: sample CLogarithmic
# (note that rand(Complex) samples uniformly from the unit square)
2 changes: 1 addition & 1 deletion src/statsfuns.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ for lfn in propertynames(StatsFuns)
m = match(r"^(.*)log(pdf|cdf|ccdf)", string(lfn))
if m !== nothing
fn = Symbol(m[1], m[2])
@eval StatsFuns.$(fn)(::Type{E}, args...; opts...) where {E<:ALog} = exp(E, StatsFuns.$(lfn)(args...; opts...))
@eval StatsFuns.$(fn)(::Type{E}, args...; opts...) where {E<:AnyLog} = exp(E, StatsFuns.$(lfn)(args...; opts...))
end
end
Loading

0 comments on commit 91569e4

Please sign in to comment.