Kotlin / multik

Multidimensional array library for Kotlin
https://kotlin.github.io/multik/
Apache License 2.0
633 stars 38 forks source link

Add support for bulk setter using primitive array #179

Open tklinchik opened 6 months ago

tklinchik commented 6 months ago

In order to update all values (by some dimension) in the NDArray there's no bulk copy operator that's efficient and as a result you need to iterate all dimensions:

  val array = mk.zeros<Float>(20, 5, 3)
  for (i in 0 until 20) {
    for (j in 0 until 5) {
      for (k in 0 until 3) {
        array[i, j, k] = computeSingleValue()
      }
    }
  }

For use cases with array of primitive values for a single dimension already available, it would be very useful to have a bulk support allowing to supply a vector of values (as a primitive array) for N-1 dimensions with a signatures as follows:

public operator fun MutableMultiArray<Float, D4>.setFloatArray(ind1: Int, ind2: Int, ind3: Int, values: FloatArray, valuesOffset: Int = 0, valuesSize: Int = values.size) public operator fun MutableMultiArray<Float, D3>.setFloatArray(ind1: Int, ind2: Int, values: FloatArray, valuesOffset: Int = 0, valuesSize: Int = values.size) public operator fun MutableMultiArray<Float, D2>.setFloatArray(ind1: Int, values: FloatArray, valuesOffset: Int = 0, valuesSize: Int = values.size)

which would eliminate expensive stride lookups for every single value set in the example above and would allow the following:

  val array = mk.zeros<Float>(20, 5, 3)
  for (i in 0 until 20) {
    for (j in 0 until 5) {
      val dim = computeOneDimension() // returning FloatArray
      ndarray.set(i, j, dim)
    }
  }

This will significantly improve performance of updating very large matrices. Also, this would be a peer of N-1 helper to get a copy of array out allowing array.get(i, j).toFloatArray() for 3D NDArray for example.