You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I need a function that, given an index in the underlying array, returns the ndarray index: [i,j,...];
I implemented it in my code (without the compilation logic of ndarray), and thought it might be useful within this project, since index is already there.
function unindex(ndarr, n)
{
const result = new Array( ndarr.shape.length );
n = n - ndarr.offset;
ndarr.stride.forEach( (stride, i)=>{
result[i] = Math.floor( n / stride );
n %= stride;
});
return result;
};
This isn't always well defined. For example if you had an ndarray with strides [0,0,0] then there would be an infinite number of inverses.
Also some elements might not have inverses. For example if you have a stride [2] and offset 1 then you wouldn't be able to compute the unindex of any odd element.
I wrote the original unindex for a very simple case: no offset, all the strides are positive, the last one is 1 etc.
I'm not very familiar with the semantics of ndarray. Just out of curiousity, what does it mean for a stride to be 0? According to wikipedia an array cannot have a stride smaller than the element size.
You're right about your first point and conclusion: if some strides are 0 index is non-injective, thus unindex cannot be a function. Moreover my implementation was broken for such cases: it returned an array filled with NaN.
Besides the implementation of unindex was also broken for negative indices (which are supported by index ).
I also agree that unindex shouldn't work for elements which don't belong to index's codomain. At the moment, though, index accepts real numbers as indices. For instance:
arr.index(0.5)=1 if arr.offset=0 ⋀ arr.stride=[2]
arr.index(0.5)=0.5 if arr.offset=0 ⋀ arr.stride=[1]
I don't know whether you care about this function at all, but I tried to implement a semantically correct version anyways.
I re-implemented unindex taking into account the previous points and making it:
return undefined for the values that make the unindex non-injective.
return NaN for the values outside of index's codomain when its domain is an array of integers.
function absFloor(n)
{
return n >= 0 ? Math.floor(n) : Math.ceil(n);
};
function unindex(ndarr, n)
{
const result = new Array( ndarr.shape.length );
n = n - ndarr.offset;
ndarr.stride.forEach( (stride, i)=>{
if( stride ) {
if( i === result.length-1 && ! Number.isInteger(n / stride) ) {
/*
* TODO: is `NaN` what we want?
* `index` seems to support fractions: if we returned `n/stride`, then `index(unindex(x)) === x || `, for this case.
result[i] = n / stride;
*/
result[i] = NaN;
return;
}
result[i] = absFloor( n / stride );
n %= stride;
}
else {
/*
* TODO: is `undefined` what we want?
* if we want `unindex(index(x)) === x` we should return a number.
result[i] = 0;
*/
}
});
return result;
};
If we want a semantically perfect version of index and unindex, and having that unindex(index(x))=x ⋁ ( isNaN(index(x)) ⋀ ∀y, unindex(y)≠x ), I believe that we should modify index(i,j,...) so that it:
fails if i,j,... ∉ ℤ (or maybe even ℕ?),
fails if at least one of the indices is larger than the size of its dimension (and maybe smaller than 0).
accepts anything (or at least undefined) for the indices whose stride is 0.
Activity
mikolalysenko commentedon Jul 12, 2016
This isn't always well defined. For example if you had an ndarray with strides
[0,0,0]then there would be an infinite number of inverses.Also some elements might not have inverses. For example if you have a stride
[2]and offset1then you wouldn't be able to compute theunindexof any odd element.As a result
unindexisn't a function.peoro commentedon Jul 12, 2016
I wrote the original
unindexfor a very simple case: no offset, all the strides are positive, the last one is 1 etc.I'm not very familiar with the semantics of
ndarray. Just out of curiousity, what does it mean for a stride to be 0? According to wikipedia an array cannot have a stride smaller than the element size.You're right about your first point and conclusion: if some strides are 0
indexis non-injective, thusunindexcannot be a function. Moreover my implementation was broken for such cases: it returned an array filled withNaN.Besides the implementation of
unindexwas also broken for negative indices (which are supported byindex).I also agree that
unindexshouldn't work for elements which don't belong toindex's codomain. At the moment, though,indexaccepts real numbers as indices. For instance:arr.index(0.5)=1 if arr.offset=0 ⋀ arr.stride=[2]arr.index(0.5)=0.5 if arr.offset=0 ⋀ arr.stride=[1]I don't know whether you care about this function at all, but I tried to implement a semantically correct version anyways.
I re-implemented
unindextaking into account the previous points and making it:undefinedfor the values that make theunindexnon-injective.NaNfor the values outside ofindex's codomain when its domain is an array of integers.This is an example of how it behaves:
If we want a semantically perfect version of
indexandunindex, and having thatunindex(index(x))=x ⋁ ( isNaN(index(x)) ⋀ ∀y, unindex(y)≠x ), I believe that we should modifyindex(i,j,...)so that it:i,j,... ∉ ℤ(or maybe evenℕ?),undefined) for the indices whose stride is 0.