The IndexIterator class, which I added as an implementation detail, has potential applications elsewhere in your extension functions (mapIndexedN for example could use it to avoid having to call linearToNIdx N times)
Awkward Side-Effects
The "more branches" there are the other special cases for the other types, which means that using this function clutters the resulting .class with a bunch of unreachable bytecode.
The index and value parameters in a lot of get/set methods have been renamed to i and v respectively, to match what Matrix does. This is because the Matrix versions of a lot of these became redundant as part of this work, and, knowing that Matrix is far more widely used than NDArray, I figured making the signature match Matrix would cause less breakage.
Matrix.kt and NDArray.kt now contain generated code
Mixed Bag
Fill no longer generates n copies of the indices array, so e.g. NDArray(1, 2, 3) { it } will result in an array with 6 references to the same IntArray instance in it. It's easy enough to add a .copy() if this is undesirable.
vararg functions apparently generate an Array.copy call on the vararg parameter. To avoid copying the dims array N times when the new inline factory function is called, I added primitive-optimized versions of get/set for linear indices and changed DefaultNDArray's primary constructor to just take an array. To avoid breaking old code, I also added a secondary constructor(shape0: Int, vararg restOfShape: Int to try to avoid breaking people who are using the deprecated DefaultNDArray(1, 2, 3) { "init" }. I could not find a way to avoid breaking DefaultNDArray(shape = *shape); any code which does this would have to remove the *
I marked getLinear/setLinear as deprecated, because get${dtype}/set${dtype} now exist.
What It Does This PR enables a syntax on NDArray similar to Kotlin's
List(5) { "init" }
, using inlines to avoid boxing primitive values.With this patch, the following code
disassebles to this on the JVM:
Positive Side Effects
.size
, like other collections.IndexIterator
class, which I added as an implementation detail, has potential applications elsewhere in your extension functions (mapIndexedN
for example could use it to avoid having to calllinearToNIdx
N times)Awkward Side-Effects
.class
with a bunch of unreachable bytecode.index
andvalue
parameters in a lot of get/set methods have been renamed toi
andv
respectively, to match what Matrix does. This is because the Matrix versions of a lot of these became redundant as part of this work, and, knowing that Matrix is far more widely used than NDArray, I figured making the signature match Matrix would cause less breakage.Mixed Bag
NDArray(1, 2, 3) { it }
will result in an array with 6 references to the sameIntArray
instance in it. It's easy enough to add a .copy() if this is undesirable.vararg
functions apparently generate anArray.copy
call on the vararg parameter. To avoid copying the dims array N times when the new inline factory function is called, I added primitive-optimized versions of get/set for linear indices and changed DefaultNDArray's primary constructor to just take an array. To avoid breaking old code, I also added a secondaryconstructor(shape0: Int, vararg restOfShape: Int
to try to avoid breaking people who are using the deprecatedDefaultNDArray(1, 2, 3) { "init" }
. I could not find a way to avoid breakingDefaultNDArray(shape = *shape)
; any code which does this would have to remove the*
getLinear
/setLinear
as deprecated, becauseget${dtype}
/set${dtype}
now exist.