Skip to content

Convert multik-api, multik-jvm, multik-default to use multiplaform. Add native and js targets for multik-jvm #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 56 commits into from
Jan 13, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
e30d5f8
Use standard reflection instead of ServiceLoader
luca992 Apr 25, 2021
5af5239
Convert multik-api, multik-jvm, multik-default to use multiplaform pl…
luca992 Apr 25, 2021
22373f3
local
luca992 Apr 26, 2021
861affe
Merge branch 'v0.0.2' into multiplatform
luca992 Apr 26, 2021
c7b31d3
Don't log error when engine not found
luca992 Apr 27, 2021
bf1b95c
remove maven-publish plugins
luca992 Apr 27, 2021
2afafd4
remove jvmJar task. Doesn't seem to be needed
luca992 Apr 27, 2021
b036f01
use mimalloc for better performance on native targets
luca992 Apr 27, 2021
e6e8994
kotlin 1.5.0-rc
luca992 Apr 27, 2021
0b47f38
Revert "remove maven-publish plugins"
luca992 Apr 27, 2021
2129b24
Fix thread access issues on native
luca992 May 6, 2021
82f2330
Merge branch 'kotlin_1.5' into multiplatform
luca992 Sep 22, 2021
2d21e28
Merge branch 'v0.0.2' into multiplatform
luca992 Sep 22, 2021
b92d96b
add js
luca992 Sep 22, 2021
81a381c
js fix
luca992 Sep 22, 2021
ed48312
kotlin 1.5.31
luca992 Sep 22, 2021
4a4bef2
Merge branch 'master' into multiplatform
luca992 Sep 22, 2021
27affa0
fix jsTests. use simplified test import
luca992 Sep 22, 2021
c35e148
Fix all test for js. Move JvmLinAlgTest to correct commonTest folder
luca992 Sep 22, 2021
152a246
reified fixes to determine NDArray data types on JS. JS tests passing ✅
luca992 Sep 23, 2021
3b29daf
init engine
luca992 Sep 23, 2021
e3f3718
Simplify setting engines/ default engine. Fix loading engine on JS
luca992 Sep 23, 2021
a000e29
Merge branch 'v0.0.2' into multiplatform
luca992 Sep 23, 2021
c15f219
move new file to common
luca992 Sep 23, 2021
693e90c
add import
luca992 Sep 23, 2021
adb6c9f
Merge branch 'v0.0.2' into multiplatform
luca992 Sep 27, 2021
2af3066
only assign framework name on apple targets. Add mac arm targets
luca992 Sep 29, 2021
2cd64aa
multik-native dependency/ import fixes
luca992 Sep 29, 2021
98aa736
enable parallel and caching options for gradle to improve compilation…
luca992 Sep 29, 2021
e4375d1
UseParallelGC
luca992 Sep 29, 2021
b81ad82
Merge branch 'v0.1.0' into multiplatform
luca992 Sep 29, 2021
1c65b23
move csv.kt to jvmMain
luca992 Sep 29, 2021
2623b93
Merge branch 'v0.1.0' into multiplatform
luca992 Dec 14, 2021
cf6f843
Merge branch 'master' into multiplatform
luca992 Dec 14, 2021
59f367e
revert re-adding toSortedSet to common
luca992 Dec 14, 2021
8c17efb
update names for JS
luca992 Dec 14, 2021
4e2281e
handle all datatypes individually and use copy into
luca992 Dec 15, 2021
c658044
fixes to make all multik-api tests pass for js
luca992 Dec 15, 2021
5fc6f13
more accurate comment
luca992 Dec 15, 2021
52ce7b8
Fixes bug causing JvmLinAlgTest tests to fail! Forgot to do size*2 🙃
luca992 Dec 15, 2021
bd16c0c
fix for js bug. ++ combined with += causes it to increment twice
luca992 Dec 15, 2021
517f53c
not used anymore. remove again
luca992 Dec 15, 2021
2471869
revert test parameter to original
luca992 Dec 15, 2021
18c997b
update to kotlin 1.6.10, increase js test timeout. fixes JS issues
luca992 Dec 15, 2021
31f263d
revert specifying heapsize and using parrallelGC
luca992 Dec 20, 2021
b5bcce0
remove -fPIC param
luca992 Dec 20, 2021
a4ba607
fix ones functions to actually use ones
luca992 Dec 20, 2021
bad9d45
remove unused import
luca992 Dec 20, 2021
a31c40b
workaround to not cast enginesProvider
luca992 Dec 20, 2021
c0ea58a
revert most reified, create two implementations of toCommonNDArray
luca992 Dec 22, 2021
4048af0
us js IR compiler. Resolves one failing test
luca992 Dec 22, 2021
827d175
Get the hashCode of the elements in it the array. not the array itself
luca992 Dec 22, 2021
493d5e7
remove old duplicate DefaultMath
luca992 Dec 29, 2021
c92dabf
move multik-default src/main to src/jvmMain so it actually is built
luca992 Dec 29, 2021
bab395f
changes that weren't added to previous commit by accident
luca992 Dec 29, 2021
4c728f0
use experimental memory model
luca992 Dec 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge branch 'v0.0.2' into multiplatform
  • Loading branch information
luca992 committed Apr 26, 2021
commit 861affe839d28782edfab6b711c73f535761e83b
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ kotlin.code.style=official
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
systemProp.kotlinVersion=1.4.32
multikVersion=0.0.1-SNAPSHOT
multikVersion=0.0.2-SNAPSHOT
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public interface LinAlg {
*/
public fun <T : Number> norm(mat: MultiArray<T, D2>, p: Int = 2): Double

public fun <T : Number, D: Dim2> solve(a: MultiArray<T, D2>, b: MultiArray<T, D>): NDArray<T, D>

/**
* Dot products of two arrays. Matrix product.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

package org.jetbrains.kotlinx.multik.ndarray.data

import org.jetbrains.kotlinx.multik.ndarray.operations.minus

@PublishedApi
@Suppress("NOTHING_TO_INLINE")
internal inline fun requireDimension(dim: Dimension, shapeSize: Int) {
Expand Down Expand Up @@ -77,7 +75,17 @@ internal inline fun <reified T : Number> Number.toPrimitiveType(): T = when (T::
} as T

//TODO(create module utils)
/*internal*/ public operator fun <T : Number> Number.compareTo(other: T): Int = (this - other).toInt()
public operator fun <T : Number> Number.compareTo(other: T): Int {
return when {
this is Float && other is Float -> this.compareTo(other)
this is Double && other is Double -> this.compareTo(other)
this is Int && other is Int -> this.compareTo(other)
this is Long && other is Long -> this.compareTo(other)
this is Short && other is Short -> this.compareTo(other)
this is Byte && other is Byte -> this.compareTo(other)
else -> this.toDouble().compareTo(other.toDouble())
}
}

@PublishedApi
internal fun IntArray.remove(pos: Int): IntArray = when (pos) {
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -9,51 +9,93 @@ package org.jetbrains.kotlinx.multik.ndarray.data
*/
public interface Indexing

/**
* Convenient Slice for start stub.
*/
public class SliceStartStub

/**
* Convenient Slice for stop stub.
*/
public class SliceEndStub

/**
* Alias name for Slice.
*/
public typealias sl = Slice.Companion

/**
* Stub start.
*/
public val sl.first: SliceStartStub
get() = SliceStartStub()

/**
* Stub stop.
*/
public val sl.last: SliceEndStub
get() = SliceEndStub()

/**
* Returns Slice with stubs the start and the stop.
*/
public val sl.bounds: Slice
get() = Slice(-1, -1, 1)

/**
* Slice class. An analogue of slices in python.
*/
public class Slice(start: Int, stop: Int, step: Int) : Indexing {
public class Slice(start: Int, stop: Int, step: Int) : Indexing, ClosedRange<Int> {

init {
if (step == 0 && start != 0 && stop != 0) throw IllegalArgumentException("Step must be non-zero.")
if (step == Int.MIN_VALUE) throw kotlin.IllegalArgumentException("Step must be greater than Int.MIN_VALUE to avoid overflow on negation.")
}

private var _start: Int = if (stop in 0 until start) stop else start
private var _stop: Int = if (_start == stop) start else stop
public companion object;

private var _start: Int = start
private var _stop: Int = stop

public val step: Int = if (step < 0) -step else step
public val start: Int get() = _start
public val step: Int = if (step < 0) throw IllegalArgumentException("Step must be positive.") else step
public override val start: Int get() = _start
public val stop: Int get() = _stop


// TODO?
public fun indices(size: Int) {
override val endInclusive: Int
get() = stop

}

public operator fun rangeTo(step: RInt): Slice = Slice(_start, _stop, step.data)

public operator fun rangeTo(step: Int): Slice = Slice(_start, _stop, step)

//todo
// override fun contains(value: Int): Boolean = value in start..end
override fun contains(value: Int): Boolean = value in start..stop

//fun isEmpty(): Boolean = start == 0 && end == 0
override fun equals(other: Any?): Boolean =
other is Slice && (isEmpty() && other.isEmpty() ||
start == other.start && stop == other.stop && step == other.step)

// override fun equals(other: Any?): Boolean =
// other is IntRange && (isEmpty() && other.isEmpty() ||
// start == other.first && end == other.last)

// override fun hashCode(): Int =
// if (isEmpty()) -1 else (31 * start + end + step)
override fun hashCode(): Int =
if (isEmpty()) -1 else (31 * start + stop + step)

override fun toString(): String = "$start..$stop..$step"
}

public companion object {
/** An empty range of values of type Int. */
public val EMPTY: Slice = Slice(0, 0, 0)
/**
* Returns Slice containing the first, the last with a step of 1.
*/
public fun IntRange.toSlice(): Slice = Slice(this.first, this.last, 1)

/**
* Returns Slice containing the first, the last with a step of 1.
*/
public fun ClosedRange<Int>.toSlice(): Slice =
when(this) {
is Slice -> this
is IntRange -> this.toSlice()
else -> throw IllegalStateException("${this::class} not supported, please use Slice or IntRange.")
}
}

/**
* Returns [RInt].
Expand All @@ -75,14 +117,23 @@ public inline class RInt(internal val data: Int) : Indexing {
}

/**
*
* Returns Slice with stub of the start.
*/
public operator fun SliceStartStub.rangeTo(that: Int): Slice = Slice(-1, that, 1)

/**
* Returns Slice with stub of the stop.
*/
public operator fun Int.rangeTo(that: SliceEndStub): Slice = Slice(this, -1, 1)

/**
* Returns Slice where stop from RInt.
*/
public operator fun Int.rangeTo(that: RInt): Slice = Slice(this, that.data, 1)

//TODO (Experimental)
/**
* Returns a slice at a specified [step].
*/
public operator fun IntProgression.rangeTo(step: Int): Slice {
public operator fun IntRange.rangeTo(step: Int): Slice {
return Slice(this.first, this.last, step)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.jetbrains.kotlinx.multik.ndarray.data

import org.jetbrains.kotlinx.multik.api.*
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class SliceTest {

@Test
fun testSlice1D() {
val a = mk.ndarrayOf(1, 2, 3, 4)


assertEquals(mk.ndarrayOf(2, 3), a[1..3])
assertTrue(a[3..1].isEmpty())
assertEquals(mk.ndarrayOf(1, 3), a[sl.bounds..2])
}

@Test
fun testSlice2D() {
val a = mk.d2array(3, 3) { it }

assertEquals(mk.ndarray(mk[mk[3, 4, 5], mk[6, 7, 8]]), a[1..3])
assertEquals(mk.ndarray(mk[mk[2], mk[5]]), a[0..2, 2..3])
assertEquals(mk.ndarrayOf(3), a[1, 0..1])
assertEquals(mk.ndarrayOf(5), a[1..2, 2])
}

@Test
fun testSlice3D() {
val a = mk.d3array(3, 3, 3) { it }

assertEquals(mk.d3array(2, 3, 3) { it + 9 }, a[1..3])
assertEquals(
mk.ndarray(mk[mk[mk[3, 4, 5], mk[6, 7, 8]], mk[mk[12, 13, 14], mk[15, 16, 17]]]),
a[0..2, 1..3, sl.bounds]
)
assertEquals(mk.ndarrayOf(15, 16), a[1, 2, 0..2])
assertEquals(mk.ndarrayOf(11, 14), a[1, 0..2, 2])
assertEquals(mk.ndarrayOf(5, 14), a[0..2, 1, 2])
assertEquals(mk.ndarray(mk[mk[4, 7], mk[13, 16]]), a[0..2, 1..3, 1])
assertEquals(mk.ndarray(mk[mk[4, 5], mk[13, 14]]), a[0..2, 1, 1..3])
assertEquals(mk.ndarray(mk[mk[10, 11], mk[13, 14]]), a[1, 0..2, 1..3])
}

@Test
fun testSlice4D() {
val a = mk.d4array(2, 2, 2, 2) { it }
assertEquals(a, a[sl.bounds])
assertEquals(mk.ndarray(mk[mk[mk[mk[5]]]]), a[0..1, 1..2, 0..1, 1..2])
assertEquals(mk.ndarray(mk[mk[mk[5]]]), a[0..1, 1, 0..1, 1..2..1])
assertEquals(mk.ndarray(mk[mk[7]]), a[0..1, 1, 1, 1..2])
assertEquals(mk.ndarrayOf(6), a[0..1, 1, 1, 0])
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,25 @@ public object DefaultLinAlg : LinAlg {

override fun <T : Number> norm(mat: MultiArray<T, D2>, p: Int): Double = JvmLinAlg.norm(mat, p)

//TODO()
override fun <T : Number, D: Dim2> solve(a: MultiArray<T, D2>, b: MultiArray<T, D>): NDArray<T, D> {
return when (a.dtype) {
DataType.FloatDataType, DataType.DoubleDataType -> NativeLinAlg.dot(a, b)
else -> throw UnsupportedOperationException()
}
}

override fun <T : Number, D : Dim2> dot(a: MultiArray<T, D2>, b: MultiArray<T, D>): NDArray<T, D> {
return when (a.dtype) {
DataType.FloatDataType -> NativeLinAlg.dot(a, b)
DataType.DoubleDataType -> NativeLinAlg.dot(a, b)
DataType.FloatDataType, DataType.DoubleDataType -> NativeLinAlg.dot(a, b)
else -> JvmLinAlg.dot(a, b)
}
}

override fun <T : Number> dot(a: MultiArray<T, D1>, b: MultiArray<T, D1>): T {
return JvmLinAlg.dot(a, b)
return when(a.dtype) {
DataType.FloatDataType, DataType.DoubleDataType -> NativeLinAlg.dot(a, b)
else -> JvmLinAlg.dot(a, b)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public object JvmLinAlg : LinAlg {
return n.pow(1 / p.toDouble())
}

override fun <T : Number, D: Dim2> solve(a: MultiArray<T, D2>, b: MultiArray<T, D>): NDArray<T, D> {
TODO("Not yet implemented")
}

override fun <T : Number, D : Dim2> dot(a: MultiArray<T, D2>, b: MultiArray<T, D>): NDArray<T, D> {
require(a.shape[1] == b.shape[0]) { "Shapes mismatch: shapes " +
"${a.shape.joinToString(prefix = "(", postfix = ")")} and " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ class JvmMathTest {
initEnginesProvider(listOf(JvmEngine()))
}

@Test
fun `test of argMax function Double`() {
val ndarray1 = mk.ndarray(mk[0.008830892, 0.7638366187, -0.0401326368965, -0.269757419187])
val ndarray2 = mk.ndarray(mk[0.0088308926050, 0.763836618743, Double.NaN, -0.2697574191872])

assertEquals(1, mk.math.argMax(ndarray1))
assertEquals(2, mk.math.argMax(ndarray2))
}

@Test
fun `test of argMax function with axis`() {
val ndarray = mk.ndarray(mk[mk[mk[50, 3], mk[1, 4]], mk[mk[2, 5], mk[6, 8]], mk[mk[7, 9], mk[10, 11]]])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,30 @@ public object NativeLinAlg : LinAlg {
TODO("Not yet implemented")
}

override fun <T : Number, D : Dim2> solve(a: MultiArray<T, D2>, b: MultiArray<T, D>): NDArray<T, D> {
require(a.shape[0] == a.shape[1]) { "Ndarray must be square: a.shape = ${a.shape.joinToString(",", "(", ")")}" }
require(a.shape[0] == b.shape[0]) { "The first dimensions of the ndarrays a and b must be match: ${a.shape[0]}(a.shape[0]) != ${b.shape[0]}(b.shape[0]" }
val ret = if (b.consistent) (b as NDArray).clone() else (b as NDArray).deepCopy()
val nhrs = if (ret.dim.d == 1) ret.shape[0] else ret.shape[1]

val info: Int = when (a.dtype) {
DataType.FloatDataType -> JniLinAlg.solve(
a.shape.first(), nhrs, a.data.getFloatArray().copyOf(), a.strides.first(),
ret.data.getFloatArray(), ret.strides.first()
)
DataType.DoubleDataType -> JniLinAlg.solve(
a.shape.first(), nhrs, a.data.getDoubleArray().copyOf(), a.strides.first(),
ret.data.getDoubleArray(), ret.strides.first()
)
else -> throw UnsupportedOperationException()
}
if (info > 0) {
throw Exception("The diagonal element of the triangular factor of a is zero, so that A is singular. The solution could not be computed.")
}

return ret
}

//TODO (Double and Number type)
override fun <T : Number, D : Dim2> dot(a: MultiArray<T, D2>, b: MultiArray<T, D>): NDArray<T, D> {
require(a.shape[1] == b.shape[0]) {
Expand Down Expand Up @@ -60,17 +84,42 @@ public object NativeLinAlg : LinAlg {
}

override fun <T : Number> dot(a: MultiArray<T, D1>, b: MultiArray<T, D1>): T {
TODO("Not yet implemented")
require(a.size == b.size) { "Vector sizes don't match: ${a.size} != ${b.size}" }
return when (a.dtype) {
DataType.FloatDataType -> {
JniLinAlg.dot(
a.size,
a.data.getFloatArray(),
a.strides.first(),
b.data.getFloatArray(),
b.strides.first()
)
}
DataType.DoubleDataType -> {
JniLinAlg.dot(
a.size,
a.data.getDoubleArray(),
a.strides.first(),
b.data.getDoubleArray(),
b.strides.first()
)
}
else -> throw UnsupportedOperationException()
} as T
}
}

private object JniLinAlg {
external fun <T : Number> pow(mat: FloatArray, n: Int, result: FloatArray): Unit
external fun <T : Number> pow(mat: DoubleArray, n: Int, result: DoubleArray): Unit
external fun <T : Number> norm(mat: FloatArray, p: Int): Double
external fun <T : Number> norm(mat: DoubleArray, p: Int): Double
external fun pow(mat: FloatArray, n: Int, result: FloatArray): Unit
external fun pow(mat: DoubleArray, n: Int, result: DoubleArray): Unit
external fun norm(mat: FloatArray, p: Int): Double
external fun norm(mat: DoubleArray, p: Int): Double
external fun solve(n: Int, nrhs: Int, a: FloatArray, strA: Int, b: FloatArray, strB: Int): Int
external fun solve(n: Int, nrhs: Int, a: DoubleArray, strA: Int, b: DoubleArray, strB: Int): Int
external fun dot(a: FloatArray, m: Int, n: Int, b: FloatArray, k: Int, c: FloatArray): Unit
external fun dot(a: DoubleArray, m: Int, n: Int, b: DoubleArray, k: Int, c: DoubleArray): Unit
external fun dot(a: FloatArray, m: Int, n: Int, b: FloatArray, c: FloatArray): Unit
external fun dot(a: DoubleArray, m: Int, n: Int, b: DoubleArray, c: DoubleArray): Unit
external fun dot(n: Int, a: FloatArray, strideA: Int, b: FloatArray, strideB: Int): Float
external fun dot(n: Int, a: DoubleArray, strideA: Int, b: DoubleArray, strideB: Int): Double
}
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.