# API

## Interface

`DensityInterface.logdensityof`

— Function`logdensityof(object, x)::Real`

Compute the logarithmic value of the density `object`

(resp. its associated density) at a given point `x`

.

```
julia> DensityKind(object)
IsDensity()
julia> logy = logdensityof(object, x); logy isa Real
true
```

See also `DensityKind`

and `densityof`

.

`DensityInterface.logdensityof`

— Method`logdensityof(object)`

Return a function that computes the logarithmic value of the density `object`

(resp. its associated density) at a given point.

```
julia> log_f = logdensityof(object); log_f isa Function
true
julia> log_f(x) == logdensityof(object, x)
true
```

`logdensityof(object)`

defaults to `Base.Fix1(logdensityof, object)`

, but may be specialized. If so, `logfuncdensity`

will typically have to be specialized for the return type of `logdensityof`

as well.

`logfuncdensity`

is the inverse of `logdensityof`

, so `logfuncdensity(log_f)`

must be equivalent to `object`

.

`DensityInterface.logfuncdensity`

— Function`logfuncdensity(log_f)`

Return a `DensityInterface`

-compatible density that is defined by a given log-density function `log_f`

:

```
julia> object = logfuncdensity(log_f);
julia> DensityKind(object)
IsDensity()
julia> logdensityof(object, x) == log_f(x)
true
```

`logfuncdensity(log_f)`

returns an instance of `DensityInterface.LogFuncDensity`

by default, but may be specialized to return something else depending on the type of `log_f`

). If so, `logdensityof`

will typically have to be specialized for the return type of `logfuncdensity`

as well.

`logfuncdensity`

is the inverse of `logdensityof`

, so the following must hold true:

`d = logfuncdensity(logdensityof(object))`

is equivalent to`object`

in respect to`logdensityof`

and`densityof`

. However,`d`

may not be equal to`object`

, especially if`DensityKind(object) == HasDensity()`

:`logfuncdensity`

always creates something that*is*density, never something that just*has*a density in some way (like a distribution or a measure in general).`logdensityof(logfuncdensity(log_f))`

is equivalent (typically equal or even identical to) to`log_f`

.

See also `DensityKind`

.

`DensityInterface.funcdensity`

— Function`funcdensity(f)`

Return a `DensityInterface`

-compatible density that is defined by a given non-log density function `f`

:

```
julia> object = funcdensity(f);
julia> DensityKind(object)
IsDensity()
julia> densityof(object, x) == f(x)
true
```

`funcdensity(f)`

returns an instance of `DensityInterface.FuncDensity`

by default, but may be specialized to return something else depending on the type of `f`

). If so, `densityof`

will typically have to be specialized for the return type of `funcdensity`

as well.

`funcdensity`

is the inverse of `densityof`

, so the following must hold true:

`d = funcdensity(densityof(object))`

is equivalent to`object`

in respect to`logdensityof`

and`densityof`

. However,`d`

may not be equal to`object`

, especially if`DensityKind(object) == HasDensity()`

:`funcdensity`

always creates something that*is*density, never something that just*has*a density in some way (like a distribution or a measure in general).`densityof(funcdensity(f))`

is equivalent (typically equal or even identical to) to`f`

.

See also `DensityKind`

.

`DensityInterface.densityof`

— Function`densityof(object, x)::Real`

Compute the value of the density `object`

(resp. its associated density) at a given point `x`

.

```
julia> DensityKind(object)
IsDensity()
julia> densityof(object, x) == exp(logdensityof(object, x))
true
```

`densityof(object, x)`

defaults to `exp(logdensityof(object, x))`

, but may be specialized.

See also `DensityKind`

and `densityof`

.

`densityof(object)`

Return a function that computes the value of the density `object`

(resp. its associated density) at a given point.

```
julia> f = densityof(object);
julia> f(x) == densityof(object, x)
true
```

`densityof(object)`

defaults to `Base.Fix1(densityof, object)`

, but may be specialized.

`DensityInterface.densityof`

— Method`densityof(object)`

Return a function that computes the value of the density `object`

(resp. its associated density) at a given point.

```
julia> f = densityof(object);
julia> f(x) == densityof(object, x)
true
```

`densityof(object)`

defaults to `Base.Fix1(densityof, object)`

, but may be specialized.

## Types

`DensityInterface.IsDensity`

— Type`struct IsDensity <: DensityKind end`

As a return value of `DensityKind(object)`

, indicates that `object`

*is* (represents) a density, like a probability density object.

See `DensityKind`

for details.

`DensityInterface.HasDensity`

— Type`struct HasDensity <: DensityKind end`

As a return value of `DensityKind(object)`

, indicates that `object`

*has* a density, like a probability distribution has a probability density.

See `DensityKind`

for details.

`DensityInterface.IsOrHasDensity`

— Type`IsOrHasDensity = Union{IsDensity, HasDensity}`

As a return value of `DensityKind(object)`

, indicates that `object`

either *is* or *has* a density, as understood by `DensityInterface`

.

See `DensityKind`

for details.

`DensityInterface.NoDensity`

— Type`struct NoDensity <: DensityKind end`

As a return value of `DensityKind(object)`

, indicates that `object`

*is not* and *does not have* a density, as understood by `DensityInterface`

.

See `DensityKind`

for details.

`DensityInterface.DensityKind`

— Type```
abstract type DensityKind end
DensityKind(object)
```

Subtypes of `DensityKind`

indicate if an `object`

*is* a density or if it *has* a density, in the sense of the `DensityInterface`

API, or if is *not* associated with a density (not compatible with `DensityInterface`

).

`DensityKind(object)`

returns either `IsDensity()`

, `HasDensity()`

or `NoDensity()`

.

In addition to the subtypes `IsDensity`

, `HasDensity`

or `NoDensity`

, a union `IsOrHasDensity = Union{IsDensity, HasDensity}`

is defined for convenience.

`DensityKind(object) isa IsOrHasDensity`

implies that `object`

is either a density itself or can be said to have an associated density. It also implies that the value of that density at given points can be calculated via `logdensityof`

and `densityof`

.

`DensityKind(object)`

defaults to `NoDensity()`

(object is not and does not have a density). For a type that *is* (directly represents) a density, like a probability density, define

`@inline DensityKind(::MyDensityType) = IsDensity()`

For a type that *has* (is associated with) a density in some way, like a probability distribution has a probability density, define

`@inline DensityKind(::MyDensityType) = HasDensity()`

`DensityInterface.LogFuncDensity`

— Type`struct DensityInterface.LogFuncDensity{F}`

Wraps a log-density function `log_f`

to make it compatible with `DensityInterface`

interface. Typically, `LogFuncDensity(log_f)`

should not be called directly, `logfuncdensity`

should be used instead.

`DensityInterface.FuncDensity`

— Type`struct DensityInterface.FuncDensity{F}`

Wraps a non-log density function `f`

to make it compatible with `DensityInterface`

interface. Typically, `FuncDensity(f)`

should not be called directly, `funcdensity`

should be used instead.

## Test utility

`DensityInterface.test_density_interface`

— Function`DensityInterface.test_density_interface(object, x, ref_logd_at_x; kwargs...)`

Test that `object`

is compatible with `DensityInterface`

.

Tests that either `DensityKind(object) isa IsOrHasDensity`

.

Also tests that `logdensityof(object, x)`

equals `ref_logd_at_x`

and that the behavior of `logdensityof(object)`

, `densityof(object, x)`

and `densityof(object)`

is consistent.

The results of `logdensityof(object, x)`

and `densityof(object, x)`

are compared to `ref_logd_at_x`

and `exp(ref_logd_at_x)`

using `isapprox`

. `kwargs...`

are forwarded to `isapprox`

.

Also tests that `d = logfuncdensity(logdensityof(object))`

returns a density (`DensityKind(d) == IsDensity()`

) that is equivalent to `object`

in respect to `logdensityof`

and `densityof`

, and that `funcdensity(densityof(object))`

behaves the same way.