Skip to content

Commit

Permalink
Merge pull request #21 from JuliaArrays/teh/multimapped
Browse files Browse the repository at this point in the history
setindex! for mappedarray(f, finv, A, B, C...) (and deprecate f_finv tuple)
  • Loading branch information
timholy authored Jul 9, 2018
2 parents a03e5f3 + da10a27 commit cc35144
Show file tree
Hide file tree
Showing 4 changed files with 395 additions and 179 deletions.
102 changes: 72 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ the package comes from the fact that `M == map(f, A)`.

## Usage

### Single source arrays

```jl
julia> using MappedArrays

Expand All @@ -24,7 +26,7 @@ julia> a = [1,4,9,16]
16

julia> b = mappedarray(sqrt, a)
4-element MappedArrays.ReadonlyMappedArray{Float64,1,Array{Int64,1},Base.#sqrt}:
4-element mappedarray(sqrt, ::Array{Int64,1}) with eltype Float64:
1.0
2.0
3.0
Expand All @@ -38,18 +40,19 @@ Note that you can't set values in the array:

```jl
julia> b[3] = 2
ERROR: indexed assignment not defined for MappedArrays.ReadonlyMappedArray{Float64,1,Array{Int64,1},Base.#sqrt}
in setindex!(::MappedArrays.ReadonlyMappedArray{Float64,1,Array{Int64,1},Base.#sqrt}, ::Int64, ::Int64) at ./abstractarray.jl:781
in eval(::Module, ::Any) at ./boot.jl:231
in macro expansion at ./REPL.jl:92 [inlined]
in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:46
ERROR: setindex! not defined for ReadonlyMappedArray{Float64,1,Array{Int64,1},typeof(sqrt)}
Stacktrace:
[1] error(::String, ::Type) at ./error.jl:42
[2] error_if_canonical_setindex at ./abstractarray.jl:1005 [inlined]
[3] setindex!(::ReadonlyMappedArray{Float64,1,Array{Int64,1},typeof(sqrt)}, ::Int64, ::Int64) at ./abstractarray.jl:996
[4] top-level scope at none:0
```

**unless** you also supply the inverse function, using `mappedarray((f, finv), A)`:
**unless** you also supply the inverse function, using `mappedarray(f, finv, A)`:

```
julia> c = mappedarray((sqrt, x->x*x), a)
4-element MappedArrays.MappedArray{Float64,1,Array{Int64,1},Base.#sqrt,##1#2}:
julia> c = mappedarray(sqrt, x->x*x, a)
4-element mappedarray(sqrt, x->x * x, ::Array{Int64,1}) with eltype Float64:
1.0
2.0
3.0
Expand All @@ -73,11 +76,13 @@ Naturally, the "backing" array `a` has to be able to represent any value that yo

```jl
julia> c[3] = 2.2
ERROR: InexactError()
in setindex!(::MappedArrays.MappedArray{Float64,1,Array{Int64,1},Base.#sqrt,##1#2}, ::Float64, ::Int64) at /home/tim/.julia/v0.5/MappedArrays/src/MappedArrays.jl:27
in eval(::Module, ::Any) at ./boot.jl:231
in macro expansion at ./REPL.jl:92 [inlined]
in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:46
ERROR: InexactError: Int64(Int64, 4.840000000000001)
Stacktrace:
[1] Type at ./float.jl:692 [inlined]
[2] convert at ./number.jl:7 [inlined]
[3] setindex! at ./array.jl:743 [inlined]
[4] setindex!(::MappedArray{Float64,1,Array{Int64,1},typeof(sqrt),getfield(Main, Symbol("##5#6"))}, ::Float64, ::Int64) at /home/tim/.julia/dev/MappedArrays/src/MappedArrays.jl:173
[5] top-level scope at none:0
```

because `2.2^2 = 4.84` is not representable as an `Int`. In contrast,
Expand All @@ -90,8 +95,8 @@ julia> a = [1.0, 4.0, 9.0, 16.0]
9.0
16.0

julia> c = mappedarray((sqrt, x->x*x), a)
4-element MappedArrays.MappedArray{Float64,1,Array{Float64,1},Base.#sqrt,##3#4}:
julia> c = mappedarray(sqrt, x->x*x, a)
4-element mappedarray(sqrt, x->x * x, ::Array{Float64,1}) with eltype Float64:
1.0
2.0
3.0
Expand All @@ -104,7 +109,7 @@ julia> a
4-element Array{Float64,1}:
1.0
4.0
4.84
4.840000000000001
16.0
```

Expand All @@ -127,7 +132,7 @@ julia> a = randn(3,5,2)
-0.315976 -0.188828 -0.567672 0.405086 1.06983

julia> b = mappedarray(abs, a)
3×5×2 MappedArrays.ReadonlyMappedArray{Float64,3,Array{Float64,3},Base.#abs}:
3×5×2 mappedarray(abs, ::Array{Float64,3}) with eltype Float64:
[:, :, 1] =
1.47716 0.323915 0.448389 0.56426 2.67922
0.255123 0.752548 0.41303 0.306604 1.5196
Expand All @@ -139,6 +144,53 @@ julia> b = mappedarray(abs, a)
0.315976 0.188828 0.567672 0.405086 1.06983
```

### Multiple source arrays

Just as `map(f, a, b)` can take multiple containers `a` and `b`, `mappedarray` can too:
```julia
julia> a = [0.1 0.2; 0.3 0.4]
2×2 Array{Float64,2}:
0.1 0.2
0.3 0.4

julia> b = [1 2; 3 4]
2×2 Array{Int64,2}:
1 2
3 4

julia> c = mappedarray(+, a, b)
2×2 mappedarray(+, ::Array{Float64,2}, ::Array{Int64,2}) with eltype Float64:
1.1 2.2
3.3 4.4
```

In some cases you can also supply an inverse function, which should return a tuple (one value for each input array):
```julia
julia> using ColorTypes

julia> redchan = [0.1 0.2; 0.3 0.4];

julia> greenchan = [0.8 0.75; 0.7 0.65];

julia> bluechan = [0 1; 0 1];

julia> m = mappedarray(RGB{Float64}, c->(red(c), green(c), blue(c)), redchan, greenchan, bluechan)
2×2 mappedarray(RGB{Float64}, getfield(Main, Symbol("##11#12"))(), ::Array{Float64,2}, ::Array{Float64,2}, ::Array{Int64,2}) with eltype RGB{Float64}:
RGB{Float64}(0.1,0.8,0.0) RGB{Float64}(0.2,0.75,1.0)
RGB{Float64}(0.3,0.7,0.0) RGB{Float64}(0.4,0.65,1.0)

julia> m[1,2] = RGB(0,0,0)
RGB{N0f8}(0.0,0.0,0.0)

julia> redchan
2×2 Array{Float64,2}:
0.1 0.0
0.3 0.4
```

Note that in some cases the function or inverse-function is too
complicated to print nicely in the summary line.

### of_eltype

This package defines a convenience method, `of_eltype`, which
Expand All @@ -149,20 +201,10 @@ Using `of_eltype` you can "convert" a series of arrays to a chosen element type:

```julia
julia> arrays = (rand(2,2), rand(Int,2,2), [0x01 0x03; 0x02 0x04])
(
[0.541018 0.223392; 0.341264 0.022014],

[2437062103055434647 4726011606246170825; -4226911569217925847 -8715663020460318733],

UInt8[0x01 0x03; 0x02 0x04])
([0.984799 0.871579; 0.106783 0.0619827], [-6481735407318330164 5092084295348224098; -6063116549749853620 -8721118838052351006], UInt8[0x01 0x03; 0x02 0x04])

julia> arraysT = map(A->of_eltype(Float64, A), arrays)
(
[0.541018 0.223392; 0.341264 0.022014],

[2.43706e18 4.72601e18; -4.22691e18 -8.71566e18],

[1.0 3.0; 2.0 4.0])
([0.984799 0.871579; 0.106783 0.0619827], [-6.48174e18 5.09208e18; -6.06312e18 -8.72112e18], [1.0 3.0; 2.0 4.0])
```

This construct is inferrable (type-stable), so it can be a useful
Expand Down
Loading

0 comments on commit cc35144

Please sign in to comment.