Skip to content
This repository has been archived by the owner on May 4, 2019. It is now read-only.

Add in-line docstring documentation #64

Merged
merged 1 commit into from
Sep 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions src/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ function Base.broadcast!(f, X::NullableArray; lift::Bool=false)
end

@eval let cache = Dict{Any, Dict{Bool, Dict{Int, Dict{Int, Any}}}}()
@doc """
`broadcast!(f, B::NullableArray, As::NullableArray...; lift::Bool=false)`
This method implements the same behavior as that of `broadcast!` when called on
regular `Array` arguments. It also includes the `lift` keyword argument, which
when set to true will lift `f` over the entries of the `As`. Lifting is
disabled by default. Note that this method's signature specifies the destination
`B` array as well as the source `As` arrays as all `NullableArray`s.
Thus, calling `broadcast!` on a arguments consisting of both `Array`s and
`NullableArray`s will fall back to the implementation of `broadcast!` in
`base/broadcast.jl`.
""" ->
function Base.broadcast!(f, B::NullableArray, As::NullableArray...; lift::Bool=false)
nd = ndims(B)
narrays = length(As)
Expand All @@ -74,19 +86,24 @@ end
end
end # let cache

@doc """
`broadcast(f, As::NullableArray...;lift::Bool=false)`
This method implements the same behavior as that of `broadcast` when called on
regular `Array` arguments. It also includes the `lift` keyword argument, which
when set to true will lift `f` over the entries of the `As`. Lifting is
disabled by default. Note that this method's signature specifies the source
`As` arrays as all `NullableArray`s. Thus, calling `broadcast!` on a arguments
consisting of both `Array`s and `NullableArray`s will fall back to the
implementation of `broadcast` in `base/broadcast.jl`.
""" ->
function Base.broadcast(f, As::NullableArray...;lift::Bool=false)
return broadcast!(f, NullableArray(eltype(Base.promote_eltype(As...)),
Base.Broadcast.broadcast_shape(As...)),
As...; lift=lift)
end

#----- broadcasted binary operations -----------------------------------------#

# The following require specialized implementations because the base/broadcast
# methods return BitArrays instead of similars of the arguments.
# An alternative to the following implementations is simply to let the base
# implementations use convert(::Type{Bool}, ::Nullable{Bool}), but this is
# slower.
# broadcasted ops
for (op, scalar_op) in (
(:(Base.(:(.==))), :(==)),
(:(Base.(:.!=)), :!=),
Expand Down
43 changes: 34 additions & 9 deletions src/indexing.jl
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
# NullableArray is dense and allows fast linear indexing.
import Base: LinearFast

#----- GENERAL INDEXING METHODS ----------------------------------------------#

Base.linearindexing{T <: NullableArray}(::Type{T}) = LinearFast()

# resolve ambiguity created by the two definitions that follow.
function Base.getindex{T, N}(X::NullableArray{T, N})
return X
end

@doc """
`getindex{T, N}(X::NullableArray{T, N}, I::Int...)`
Retrieve a single entry from a `NullableArray`. If the value in the entry
designated by `I` is present, then it will be returned wrapped in a
`Nullable{T}` container. If the value is missing, then this method returns
`Nullable{T}()`.
""" ->
# Extract a scalar element from a `NullableArray`.
@inline function Base.getindex{T, N}(X::NullableArray{T, N}, I::Int...)
if isbits(T)
Expand All @@ -23,13 +29,28 @@ end
end
end

@doc """
`getindex{T, N}(X::NullableArray{T, N}, I::Nullable{Int}...)`
Just as above, with the additional behavior that this method throws an error if
any component of the index `I` is null.
""" ->
@inline function Base.getindex{T, N}(X::NullableArray{T, N},
I::Nullable{Int}...)
anynull(I) && throw(NullException())
values = [ get(i) for i in I ]
return getindex(X, values...)
end

@doc """
`setindex!(X::NullableArray, v::Nullable, I::Int...)`
Set the entry of `X` at position `I` equal to a `Nullable` value `v`. If
`v` is null, then only `X.isnull` is updated to indicate that the entry at
index `I` is null. If `v` is not null, then `X.isnull` is updated to indicate
that the entry at index `I` is present and `X.values` is updated to store the
value wrapped in `v`.
""" ->
# Insert a scalar element from a `NullableArray` from a `Nullable` value.
@inline function Base.setindex!(X::NullableArray, v::Nullable, I::Int...)
if isnull(v)
Expand All @@ -41,15 +62,20 @@ end
return v
end

@doc """
`setindex!(X::NullableArray, v::Any, I::Int...)`
Set the entry of `X` at position `I` equal to `v`. This method always updates
`X.isnull` to indicate that the entry at index `I` is present and `X.values`
to store `v` at `I`.
""" ->
# Insert a scalar element from a `NullableArray` from a non-Nullable value.
@inline function Base.setindex!(X::NullableArray, v::Any, I::Int...)
X.values[I...] = v
X.isnull[I...] = false
return v
end

#----- UNSAFE INDEXING METHODS -----------------------------------------------#

function unsafe_getindex_notnull(X::NullableArray, I::Int...)
return Nullable(getindex(X.values, I...))
end
Expand All @@ -58,8 +84,6 @@ function unsafe_getvalue_notnull(X::NullableArray, I::Int...)
return getindex(X.values, I...)
end

# ----- Base._checkbounds ----------------------------------------------------#

function Base.checkbounds{T<:Real}(::Type{Bool}, sz::Int, x::Nullable{T})
isnull(x) ? throw(NullException()) : checkbounds(Bool, sz, get(x))
end
Expand All @@ -79,15 +103,16 @@ function Base.checkbounds{T<:Real}(::Type{Bool}, sz::Int, I::NullableArray{T})
return inbounds
end

# ----- Base.to_index --------------------------------------------------------#

function Base.to_index(X::NullableArray)
anynull(X) && throw(NullException())
Base.to_index(X.values)
end

# ----- nullify! --------------------------------------------------------------#
@doc """
`nullify!(X::NullableArray, I...)`
This is a convenience method to set the entry of `X` at index `I` to be null
""" ->
function nullify!(X::NullableArray, I...)
setindex!(X, Nullable{eltype(X)}(), I...)
end
18 changes: 16 additions & 2 deletions src/map.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using Base.Cartesian

# utilities

function gen_nullcheck(narrays::Int)
As = [symbol("A_"*string(i)) for i = 1:narrays]
e_nullcheck = :($(As[1]).isnull[i])
Expand Down Expand Up @@ -131,6 +129,14 @@ end

# Base.map!
@eval let cache = Dict{Bool, Dict{Int, Dict{Base.Callable, Function}}}()
@doc """
`map!{F}(f::F, dest::NullableArray, As::AbstractArray...; lift::Bool=false)`
This method implements the same behavior as that of `map!` when called on
regular `Array` arguments. It also includes the `lift` keyword argument, which
when set to true will lift `f` over the entries of the `As`. Lifting is
disabled by default.
""" ->
function Base.map!{F}(f::F, dest::NullableArray, As::AbstractArray...;
lift::Bool=false)
narrays = length(As)
Expand All @@ -148,6 +154,14 @@ Base.map!{F}(f::F, X::NullableArray; lift::Bool=false) = map!(f, X, X; lift=lift

# Base.map
@eval let cache = Dict{Int, Dict{Base.Callable, Function}}()
@doc """
`map{F}(f::F, As::AbstractArray...; lift::Bool=false)`
This method implements the same behavior as that of `map!` when called on
regular `Array` arguments. It also includes the `lift` keyword argument, which
when set to true will lift `f` over the entries of the `As`. Lifting is
disabled by default.
""" ->
function Base.map{F}(f::F, As::NullableArray...; lift::Bool=false)
narrays = length(As)
_map_to! = gensym()
Expand Down
Loading