Is there a general recommendation for dealing with the case when a
function encounters two arrays with different index sets? Eg

OffsetArray(1:5,1:5) + OffsetArray(1:5, -2:2)

currently gives a DimensionMismatch exception via promote_shape, so
perhaps one should simply rely on what the latter does. But one can
imagine other options too (eg all unrepresented indices as 0, etc). If
there is a blog post or issue summarizing the options, I would be
interested in reading it (could not find anything).

On Tue, Nov 01 2016, Tim Holy wrote:

> There's still a simple model: the indices are the *key* of the entry. Think
> about an array as a very special Dict. You could create a Dict with integer
> keys, let's say from -2:5. Presumably you wouldn't be exactly happy if
> there were some magical way that the number you originally stored as `d[-1]
> = 3.2` were alternatively accessible as `d[2]`, simply because the smallest
> index was -2 and therefore 3.2 is the "second" entry?
>
> Like a Dict, for an array the value always goes with the key (the indices).
> Perhaps this will help:
> ```
> julia> using OffsetArrays
>
> julia> a = OffsetArray(rand(11), -5:5)
> OffsetArrays.OffsetArray{Float64,1,Array{Float64,1}} with indices -5:5:
>  0.815289
>  0.0043941
>  0.00403153
>  0.478065
>  0.150709
>  0.256156
>  0.934703
>  0.672495
>  0.428721
>  0.242469
>  0.43742
>
> julia> idx = OffsetArray(-1:1, -1:1)
> OffsetArrays.OffsetArray{Int64,1,UnitRange{Int64}} with indices -1:1:
>  -1
>   0
>   1
>
> julia> b = a[idx]
> OffsetArrays.OffsetArray{Float64,1,Array{Float64,1}} with indices -1:1:
>  0.150709
>  0.256156
>  0.934703
>
> julia> a[-1]
> 0.15070935766983662
>
> julia> b[-1]
> 0.15070935766983662
> ```
> So indexing `b = a[idx]` means that `b[j] = a[idx[j]]`. Does that help?
>
> Best,
> --Tim
>
> On Tue, Nov 1, 2016 at 3:36 PM, Bob Portmann <bobportm...@gmail.com> wrote:
>
>> Like I said, no real practical experience yet. The increase in complexity
>> that I fear is the loss of, e.g., writing arr[2,3] and having it not be the
>> element in the 2nd row and third column (i.e., the loss of a simple model
>> of how things are laid out). Maybe my fears are unfounded. Others don't
>> seem concerned it would seem.
>>
>> I'll check out those packages that you mention.
>>
>> Thanks,
>> Bob
>>
>> On Sun, Oct 30, 2016 at 2:29 PM, Tim Holy <tim.h...@gmail.com> wrote:
>>
>>> I'm afraid I still don't understand the claimed big increment in
>>> complexity. First, let's distinguish "generic offset arrays" from the
>>> OffsetArrays.jl package. If you're happy using OffsetArrays, you don't have
>>> to write your own offset-array type. Being able to use an established &
>>> tested package reduces your burden a lot, and you can ignore the second
>>> half of the devdocs page entirely.
>>>
>>> If you just want to *use* OffsetArrays.jl, the basic changes in coding
>>> style for writing indices-aware code are:
>>>
>>> - any place you used to call `size`, you probably want to call `indices`
>>> instead (and likely make minor adjustments elsewhere, since `incides`
>>> returns a tuple-of-ranges---but such changes tend to be very obvious);
>>> - check all uses of `similar`; some will stay as-is, other will migrate
>>> to `similar(f, inds)` style.
>>>
>>> In my experience, that's just about it. The devdocs goes into quite a lot
>>> of detail to explain the rationale, but really the actual changes are quite
>>> small. While you can't quite do it via `grep` and `sed`, to me that just
>>> doesn't seem complicated.
>>>
>>> Where the pain comes is that if you're converting old code, you sometimes
>>> have to think your way through it again---"hmm, what do I really mean by
>>> this index"? If your code had complicated indexing the first time you wrote
>>> it, unfortunately you're going to have to think about it carefully again;
>>> so in some cases, "porting" code is almost as bad as writing it the first
>>> time. However, if you write indices-aware code in the first place, in my
>>> experience the added burden is almost negligible, and in quite a few cases
>>> the ability to offset array indices makes things *easier* (e.g., "padding"
>>> an array on its edges is oh-so-much-clearer than it used to be, it's like a
>>> different world). That's the whole reason I implemented this facility in
>>> julia-0.5: to make life easier, not to make it harder. (Personally I think
>>> the whole argument over 0-based and 1-based indexing is stupid; it's the
>>> ability to use arbitrary indices that I find interesting & useful, and it
>>> makes most of my code prettier.)
>>>
>>> For examples of packages that use OffsetArrays, check the following:
>>> - CatIndices
>>> - FFTViews
>>> - ImageFiltering
>>>
>>> ImageFiltering is a mixed bag: there's a small performance penalty in a
>>> few cases (even if you use @unsafe) because that LLVM doesn't always
>>> optimize code as well as it could in principle (maybe @polly will help
>>> someday...). Because image filtering is an extraordinarily
>>> performance-sensitive operation, there are a few places where I had to make
>>> some yucky hand optimizations.
>>>
>>> Again, I'm very happy to continue this conversation---I'd really like to
>>> understand your concern, but without a concrete example I confess I'm lost.
>>>
>>> Best,
>>> --Tim
>>>
>>>
>>> On Sat, Oct 29, 2016 at 8:44 PM, Bob Portmann <bobportm...@gmail.com>
>>> wrote:
>>>
>>>> Thanks for the thoughtful response. I hope you'll tolerate one reply in
>>>> the "abstract".
>>>>
>>>> I am resisting the big change that occurred in 0.5. In 0.4 and earlier
>>>> if one declares an array as an `AbstractArray` in a function then one knew
>>>> that the indices were one based (a nice simple model, even if it is hated
>>>> by many). In 0.5, if one wants to write general code, then one has to
>>>> assume that arrays can have ANY indices. And one needs to write code using
>>>> more abstract tools. This seems to me to be a large cost in complexity for
>>>> the small subset of cases where offset indices are helpful. This is the
>>>> core issue to me.
>>>>
>>>> One way around this, it would seem, is to declare arrays as `::Array`
>>>> and not `::AbstractArray` in functions (if one want to be sure they are
>>>> `OneTo`). But then one gives up accepting many types of arrays that would
>>>> pose no problem (e.g, DistributedArrays with OneTo indices). Thus, I'm
>>>> proposing to have a high level abstract type that would capture all arrays
>>>> types that can be assumed to be `OneTo`. Then one can write library
>>>> functions against that type. This alone would help I think.
>>>>
>>>> The auto-conversion is an extra step that I thought might work since it
>>>> is (I think) low cost to convert an `OffsetArray` to a `OneTo` array . Thus
>>>> if you passed an OffsetArray to a function that takes the abstract OneTo
>>>> type (I kept its name AbstractArray above but that need not be its name)
>>>> you expect that if it returned a `similar` array it would be of `OneTo`
>>>> type. You would then have to convert it back to an OffsetArray type. It
>>>> would probably be easy to write one line functions to do this for you. If
>>>> it was sparse I assume it would remain so. It would be up to the writer of
>>>> the new OffsetArray type to declare what type it would convert to in the
>>>> OneTo array abstract tree.
>>>>
>>>> Does this help?
>>>>
>>>> Bob
>>>>
>>>> ps I don't have any concrete examples yet because OffsetArrays are so
>>>> scarce in the julia ecosystem. I'm just looking ahead to a world where it
>>>> will no longer be possible to assume AbstractArrays are OneTo. This seems
>>>> more painful than telling the 0-based crowd to code against 1-based arrays.
>>>>
>>>>
>>>> On Sat, Oct 29, 2016 at 10:40 AM, Tim Holy <tim.h...@gmail.com> wrote:
>>>>
>>>>> I should add, abstract discussions are all well and good, but I fully
>>>>> recognize you may have something very specific in mind and my answer
>>>>> simply
>>>>> fails to understand your concern. If you can give one or more concrete
>>>>> examples of where the current system is either bug-prone or a pain in
>>>>> the
>>>>> neck, I'd love to see what you mean.
>>>>>
>>>>> Best,
>>>>> --Tim
>>>>>
>>>>> On Thursday, October 27, 2016 5:21:26 PM CDT Bob Portmann wrote:
>>>>> > TL;DR I think the type system should take care of converting between
>>>>> > different types of arrays and thus free the user to code against the
>>>>> type
>>>>> > of array they want (OneTo, ZeroTo, Offset, etc).
>>>>> >
>>>>> > Maybe I have a deep mis-understanding of how the new generalized
>>>>> offset
>>>>> > arrays are suppose to work in Julia. If so I'd be happy to be set
>>>>> straight.
>>>>> > If not then I think the present system will lead to unnecessary
>>>>> complexity
>>>>> > and bug-ridden code. In the present system one can define array types
>>>>> that
>>>>> > are not one-based but can have arbitrary offsets. This is a great
>>>>> idea but
>>>>> > to make it work a very general system for indexing relative to the
>>>>> ends of
>>>>> > the array has been devised. If one writes a function that accepts an
>>>>> > `AbstractArray` then one MUST use this more general system or produce
>>>>> bugs
>>>>> > when e.g. a `ZeroToArray` is passed in. This puts a large burden on
>>>>> writers
>>>>> > of library code that works on arrays and I think is an unnecessary
>>>>> > complexity.
>>>>> >
>>>>> > Since Fortran arrays are a nice example let look at the situation in
>>>>> > Fortran. If I define an array in a function `real arr(-10:10)` then I
>>>>> would
>>>>> > index it using indices that range from -10 to 10. If I pass this into
>>>>> > another function that declared the array using its total size (usually
>>>>> > passed in separately or in a parameter statement) `real arr(21)` then
>>>>> in
>>>>> > that subroutine one would index the array using "normal" indices that
>>>>> range
>>>>> > from 1 to 21. I.E., you state in the function how you want to treat
>>>>> the
>>>>> > array and are not forced to work with in offset form unless you want
>>>>> to. In
>>>>> > my opinion, this is what makes using offset arrays in Fortran sane
>>>>> and is
>>>>> > the key thing that Julia should try to emulate.
>>>>> >
>>>>> > One way to get this behavior in Julia would be to use the type system
>>>>> and
>>>>> > `convert`. Since `AbstractArray` has meant until 0.5 a `OneTo` array I
>>>>> > think it is wise that it remain that way so that all old code will
>>>>> work
>>>>> > unchanged (even with the new array types). Thus, I propose adding a
>>>>> new
>>>>> > top-level type above AbstractArray type to capture all arrays
>>>>> something
>>>>> > like:
>>>>> >
>>>>> > ```
>>>>> > Array{T,N} <: DenseArray{T,N} <: AbstractArray{T,N} <:
>>>>> > AbstractAllArray{T,N} <: Any
>>>>> > ```
>>>>> >
>>>>> > And the offset arrays would be subtypes of `AbstractAllArrays` on a
>>>>> > different branch
>>>>> >
>>>>> > ```
>>>>> > OffsetArray{T,N} <: AbstractOffsetArray{T,N} <: AbstractAllArray{T,N}
>>>>> <: Any
>>>>> > ```
>>>>> >
>>>>> > And similarly for `ZeroToArray`.
>>>>> >
>>>>> > Then, if one declares an Array as
>>>>> >
>>>>> > ```
>>>>> > function func(arr::AbstractArray)
>>>>> > ```
>>>>> >
>>>>> > one can safely assume it is a 1-based Array inside `func`. If an
>>>>> offset
>>>>> > array is passed into `func` then it is automatically converted to a
>>>>> `OneTo`
>>>>> > array inside `func`. This is the key point of this proposal and is
>>>>> similar
>>>>> > to the auto-conversion of, e.g., Int to Floats in a function call.
>>>>> > Similarly if one declares an array as a `ZeroToArray` in a function
>>>>> and
>>>>> > passes in an `Array` then it will be converted to a `ZeroToArray` in
>>>>> the
>>>>> > function. Some conversions would need more information and thus would
>>>>> be
>>>>> > disallowed (e.g., `Array` to `OffsetArray`). I think this system
>>>>> would go a
>>>>> > long way towards making `ZeroToArray`s and `OffsetArray`s simple to
>>>>> use in
>>>>> > Julia w/o using the generalized indexing techniques introduced in
>>>>> Julia
>>>>> > 0.5. Note that it would still be possible to use the
>>>>> `AbstractAllArray`
>>>>> > type and accept all arrays w/o conversion and use the generalized
>>>>> indexing
>>>>> > techniques.
>>>>> >
>>>>> > I'm curious what people think about this.
>>>>> >
>>>>> > Bob
>>>>> >
>>>>> > ps Paste into github to see in formatted form. I'm not sure how to
>>>>> get that
>>>>> > in an email.
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>

Reply via email to