Skip to content

Commit 2874672

Browse files
authored
Merge pull request #167 from Kotlin/develop
v0.2.2
2 parents fe47e1b + f445518 commit 2874672

File tree

42 files changed

+897
-173
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+897
-173
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ repositories {
2828
}
2929
3030
dependencies {
31-
implementation "org.jetbrains.kotlinx:multik-core:0.2.0"
32-
implementation "org.jetbrains.kotlinx:multik-default:0.2.0"
31+
implementation "org.jetbrains.kotlinx:multik-core:0.2.2"
32+
implementation "org.jetbrains.kotlinx:multik-default:0.2.2"
3333
}
3434
```
3535

@@ -40,8 +40,8 @@ repositories {
4040
}
4141

4242
dependencies {
43-
implementation("org.jetbrains.kotlinx:multik-core:0.2.0")
44-
implementation("org.jetbrains.kotlinx:multik-default:0.2.0")
43+
implementation("org.jetbrains.kotlinx:multik-core:0.2.2")
44+
implementation("org.jetbrains.kotlinx:multik-default:0.2.2")
4545
}
4646
```
4747

@@ -52,7 +52,7 @@ kotlin {
5252
sourceSets {
5353
val commonMain by getting {
5454
dependencies {
55-
implementation("org.jetbrains.kotlinx:multik-core:0.2.0")
55+
implementation("org.jetbrains.kotlinx:multik-core:0.2.2")
5656
}
5757
}
5858
}
@@ -66,7 +66,7 @@ kotlin {
6666
sourceSets {
6767
val jvmName by getting {
6868
dependencies {
69-
implementation("org.jetbrains.kotlinx:multik-core-jvm:0.2.0")
69+
implementation("org.jetbrains.kotlinx:multik-core-jvm:0.2.2")
7070
}
7171
}
7272
}

gradle.properties

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
kotlin.code.style=official
2-
multik_version=0.2.1
2+
multik_version=0.2.2
33

44
# Kotlin
5-
systemProp.kotlin_version=1.7.10
5+
systemProp.kotlin_version=1.8.21
66
group=org.jetbrains.kotlinx
77

88
# Dependencies
9-
systemProp.nexus_version=1.1.0
10-
systemProp.dokka_version=1.7.10
11-
openblas_version=0.3.19
12-
common_csv_version=1.9.0
9+
systemProp.nexus_version=1.3.0
10+
systemProp.dokka_version=1.8.10
11+
openblas_version=0.3.23
12+
common_csv_version=1.10.0
1313

1414
# Gradle
1515
org.gradle.parallel=true
@@ -22,7 +22,6 @@ kotlin.mpp.enableCInteropCommonization=true
2222
# Native
2323
kotlin.native.cacheKind.linuxX64=static
2424
kotlin.native.cacheKind.iosArm64=static
25-
kotlin.native.binary.memoryModel=experimental
2625

2726
# Settings
2827
kotlin.incremental.multiplatform=true

multik-core/build.gradle.kts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@ kotlin {
3232
iosArm64()
3333
iosSimulatorArm64()
3434
iosX64()
35+
wasm {
36+
browser {
37+
testTask {
38+
/*
39+
https://youtrack.jetbrains.com/issue/KT-56633
40+
https://youtrack.jetbrains.com/issue/KT-56159
41+
*/
42+
this.enabled = false // fixed in 1.9.0/1.9.20
43+
}
44+
}
45+
}
3546
js(IR) {
3647
val timeoutMs = "1000000"
3748
browser{
@@ -50,12 +61,6 @@ kotlin {
5061
}
5162
}
5263

53-
targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
54-
binaries.all {
55-
freeCompilerArgs = freeCompilerArgs + "-Xallocator=std"
56-
}
57-
}
58-
5964
sourceSets {
6065
val commonMain by getting {
6166
}
@@ -68,6 +73,7 @@ kotlin {
6873
dependencies {
6974
implementation(kotlin("reflect"))
7075
implementation("org.apache.commons:commons-csv:$common_csv_version")
76+
implementation("org.jetbrains.bio:npy:0.3.5")
7177
}
7278
}
7379
val nativeMain by creating {

multik-core/src/jvmMain/kotlin/org/jetbrains/kotlinx/multik/api/Engine.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.jetbrains.kotlinx.multik.api
22

33
import java.util.*
4+
import java.util.concurrent.ConcurrentHashMap
45

56
/**
67
* Engine Provider for JVM.
@@ -17,5 +18,5 @@ public actual fun enginesProvider(): Map<EngineType, Engine> {
1718
)
1819
}
1920

20-
return engineList.associateBy { it.type }
21+
return ConcurrentHashMap(engineList.associateBy { it.type })
2122
}

multik-core/src/jvmMain/kotlin/org/jetbrains/kotlinx/multik/api/io/csv.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ import java.util.zip.GZIPInputStream
2222
* @param delimiter separator between elements
2323
* @param charset character encoding, by default is UTF_8
2424
*/
25-
public inline fun <reified T : Any, reified D : Dim2> Multik.read(
25+
public inline fun <reified T : Any, reified D : Dim2> Multik.readCSV(
2626
fileName: String, delimiter: Char = ',', charset: Charset = Charsets.UTF_8
27-
): NDArray<T, D> = read(fileName, DataType.ofKClass(T::class), dimensionClassOf<D>(), delimiter, charset)
27+
): NDArray<T, D> = readCSV(fileName, DataType.ofKClass(T::class), dimensionClassOf<D>(), delimiter, charset)
2828

2929
/**
3030
* Returns an NDArray of type [T] and [D] dimension read from csv file.
@@ -35,13 +35,13 @@ public inline fun <reified T : Any, reified D : Dim2> Multik.read(
3535
* @param delimiter separator between elements
3636
* @param charset character encoding, by default is UTF_8
3737
*/
38-
public fun <T, D : Dim2> Multik.read(
38+
public fun <T, D : Dim2> Multik.readCSV(
3939
fileName: String, dtype: DataType, dim: Dim2,
4040
delimiter: Char = ',', charset: Charset = Charsets.UTF_8
4141
): NDArray<T, D> {
4242
val file = File(fileName)
4343
if (!file.exists()) throw NoSuchFileException(file)
44-
return read(file, dtype, dim, delimiter, charset)
44+
return readCSV(file, dtype, dim, delimiter, charset)
4545
}
4646

4747
/**
@@ -69,9 +69,9 @@ public fun Multik.readRaw(
6969
* @param delimiter separator between elements
7070
* @param charset character encoding, by default is UTF_8
7171
*/
72-
public inline fun <reified T : Any, reified D : Dim2> Multik.read(
72+
public inline fun <reified T : Any, reified D : Dim2> Multik.readCSV(
7373
file: File, delimiter: Char = ',', charset: Charset = Charsets.UTF_8
74-
): NDArray<T, D> = read(file, DataType.ofKClass(T::class), dimensionClassOf<D>(), delimiter, charset)
74+
): NDArray<T, D> = readCSV(file, DataType.ofKClass(T::class), dimensionClassOf<D>(), delimiter, charset)
7575

7676
/**
7777
* Returns an NDArray of type [T] and [D] dimension read from csv file.
@@ -82,7 +82,7 @@ public inline fun <reified T : Any, reified D : Dim2> Multik.read(
8282
* @param delimiter separator between elements
8383
* @param charset character encoding, by default is UTF_8
8484
*/
85-
public fun <T, D : Dim2> Multik.read(
85+
public fun <T, D : Dim2> Multik.readCSV(
8686
file: File, dtype: DataType, dim: Dim2,
8787
delimiter: Char = ',', charset: Charset = Charsets.UTF_8
8888
): NDArray<T, D> =
@@ -209,7 +209,7 @@ private fun isCompressed(file: File) = listOf("gz", "zip").contains(file.extensi
209209
* @param file file where the data will be written, if the file does not exist, it will be created
210210
* @param delimiter separator between elements
211211
*/
212-
public fun <T, D : Dim2> Multik.write(file: File, ndarray: NDArray<T, D>, delimiter: Char = ','): Unit =
212+
public fun <T, D : Dim2> Multik.writeCSV(file: File, ndarray: NDArray<T, D>, delimiter: Char = ','): Unit =
213213
writeCSV(FileWriter(file), ndarray, CSVFormat.Builder.create(CSVFormat.DEFAULT).setDelimiter(delimiter).build())
214214

215215
/**
@@ -219,7 +219,7 @@ public fun <T, D : Dim2> Multik.write(file: File, ndarray: NDArray<T, D>, delimi
219219
* @param path file path where the data will be written
220220
* @param delimiter separator between elements
221221
*/
222-
public fun <T, D : Dim2> Multik.write(path: String, ndarray: NDArray<T, D>, delimiter: Char = ','): Unit =
222+
public fun <T, D : Dim2> Multik.writeCSV(path: String, ndarray: NDArray<T, D>, delimiter: Char = ','): Unit =
223223
writeCSV(FileWriter(path), ndarray, CSVFormat.Builder.create(CSVFormat.DEFAULT).setDelimiter(delimiter).build())
224224

225225
/**
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package org.jetbrains.kotlinx.multik.api.io
2+
3+
import org.jetbrains.kotlinx.multik.api.Multik
4+
import org.jetbrains.kotlinx.multik.ndarray.data.*
5+
import java.io.File
6+
import java.nio.file.Path
7+
import kotlin.io.path.Path
8+
import kotlin.io.path.extension
9+
import kotlin.io.path.notExists
10+
11+
@PublishedApi
12+
internal enum class FileFormats(val extension: String) {
13+
NPY("npy"),
14+
NPZ("npz"),
15+
CSV("csv"),
16+
}
17+
18+
public inline fun <reified T : Any, reified D : Dimension> Multik.read(fileName: String): NDArray<T, D> =
19+
this.read(Path(fileName))
20+
21+
public inline fun <reified T : Any, reified D : Dimension> Multik.read(file: File): NDArray<T, D> = this.read(file.path)
22+
23+
public inline fun <reified T : Any, reified D : Dimension> Multik.read(path: Path): NDArray<T, D> =
24+
this.read(path, DataType.ofKClass(T::class), dimensionClassOf<D>())
25+
26+
public fun <T : Any, D : Dimension> Multik.read(path: Path, dtype: DataType, dim: D): NDArray<T, D> {
27+
if (path.notExists()) throw NoSuchFileException(path.toFile())
28+
return when (path.extension) {
29+
FileFormats.NPY.extension -> {
30+
if (dtype.isComplex()) throw Exception("NPY format only supports Number types")
31+
this.readNPY(path, dtype, dim)
32+
}
33+
34+
FileFormats.CSV.extension -> {
35+
if (dim.d > 2) throw Exception("CSV format only supports 1 and 2 dimensions")
36+
this.readRaw(path.toFile(), dtype, dim as Dim2) as NDArray<T, D>
37+
}
38+
39+
else -> throw Exception("Format ${path.extension} does not support reading ndarrays. If it is `npz` format, try `mk.readNPZ`")
40+
}
41+
}
42+
43+
public fun Multik.write(fileName: String, ndarray: NDArray<*, *>): Unit =
44+
this.write(Path(fileName), ndarray)
45+
46+
public fun Multik.write(file: File, ndarray: NDArray<*, *>): Unit =
47+
this.write(file.toPath(), ndarray)
48+
49+
public fun Multik.write(path: Path, ndarray: NDArray<*, *>): Unit =
50+
when (path.extension) {
51+
FileFormats.NPY.extension -> {
52+
require(ndarray.dtype != DataType.ComplexFloatDataType || ndarray.dtype != DataType.ComplexFloatDataType) {
53+
"NPY format does not support complex numbers."
54+
}
55+
this.writeNPY(path, ndarray as NDArray<out Number, *>)
56+
}
57+
58+
FileFormats.CSV.extension -> {
59+
require(ndarray.dim.d < 2) { TODO() }
60+
this.writeCSV(path.toFile(), ndarray as NDArray<*, out Dim2>)
61+
}
62+
63+
else -> throw Exception("Unknown format `${path.extension}`. Please use one of the supported formats: `npy`, `csv`.")
64+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package org.jetbrains.kotlinx.multik.api.io
2+
3+
import org.jetbrains.bio.npy.NpyArray
4+
import org.jetbrains.bio.npy.NpyFile
5+
import org.jetbrains.bio.npy.NpzFile
6+
import org.jetbrains.kotlinx.multik.api.Multik
7+
import org.jetbrains.kotlinx.multik.ndarray.data.*
8+
import java.io.File
9+
import java.nio.file.Path
10+
import kotlin.io.path.Path
11+
import kotlin.io.path.notExists
12+
13+
public inline fun <reified T : Number, reified D : Dimension> Multik.readNPY(fileName: String): NDArray<T, D> =
14+
readNPY(Path(fileName), DataType.ofKClass(T::class), dimensionClassOf<D>())
15+
16+
public inline fun <reified T : Number, reified D : Dimension> Multik.readNPY(file: File): NDArray<T, D> =
17+
readNPY(file.toPath(), DataType.ofKClass(T::class), dimensionClassOf<D>())
18+
19+
public inline fun <reified T : Number, reified D : Dimension> Multik.readNPY(path: Path): NDArray<T, D> {
20+
if (path.notExists()) throw NoSuchFileException(path.toFile())
21+
return readNPY(path, DataType.ofKClass(T::class), dimensionClassOf<D>())
22+
}
23+
24+
public fun <T : Any, D : Dimension> Multik.readNPY(path: Path, dtype: DataType, dim: D): NDArray<T, D> {
25+
if (dtype.isComplex()) throw Exception("NPY format only supports Number types")
26+
val npyArray: NpyArray = NpyFile.read(path)
27+
require(npyArray.shape.size == dim.d) { "Not match dimensions: shape of npy array = ${npyArray.shape.joinToString()}, and dimension = ${dim.d}" }
28+
29+
val data: MemoryView<T> = when (dtype) {
30+
DataType.DoubleDataType -> MemoryViewDoubleArray(npyArray.asDoubleArray())
31+
DataType.FloatDataType -> MemoryViewFloatArray(npyArray.asFloatArray())
32+
DataType.IntDataType -> MemoryViewIntArray(npyArray.asIntArray())
33+
DataType.LongDataType -> MemoryViewLongArray(npyArray.asLongArray())
34+
DataType.ShortDataType -> MemoryViewShortArray(npyArray.asShortArray())
35+
DataType.ByteDataType -> MemoryViewByteArray(npyArray.asByteArray())
36+
else -> throw Exception("not supported complex arrays")
37+
} as MemoryView<T>
38+
39+
return NDArray(data, shape = npyArray.shape, dim = dim)
40+
}
41+
42+
public fun Multik.readNPZ(fileName: String): List<NDArray<out Number, out DimN>> =
43+
readNPZ(Path(fileName))
44+
45+
public fun Multik.readNPZ(file: File): List<NDArray<*, out DimN>> =
46+
readNPZ(file.toPath())
47+
48+
public fun Multik.readNPZ(path: Path): List<NDArray<out Number, out DimN>> {
49+
return NpzFile.read(path).use {
50+
val entries = it.introspect()
51+
entries.map { entry ->
52+
val npyArray = it[entry.name]
53+
val data = when (entry.type.kotlin) {
54+
DataType.DoubleDataType.clazz -> MemoryViewDoubleArray(npyArray.asDoubleArray())
55+
DataType.FloatDataType.clazz -> MemoryViewFloatArray(npyArray.asFloatArray())
56+
DataType.IntDataType.clazz -> MemoryViewIntArray(npyArray.asIntArray())
57+
DataType.LongDataType.clazz -> MemoryViewLongArray(npyArray.asLongArray())
58+
DataType.ShortDataType.clazz -> MemoryViewShortArray(npyArray.asShortArray())
59+
DataType.ByteDataType.clazz -> MemoryViewByteArray(npyArray.asByteArray())
60+
else -> TODO()
61+
}
62+
NDArray(data, shape = npyArray.shape, dim = dimensionOf(npyArray.shape.size))
63+
}
64+
}
65+
}
66+
67+
public fun <T : Number, D : Dimension> Multik.writeNPY(fileName: String, ndArray: NDArray<T, D>): Unit =
68+
this.writeNPY(Path(fileName), ndArray)
69+
70+
public fun <T : Number, D : Dimension> Multik.writeNPY(file: File, ndArray: NDArray<T, D>): Unit =
71+
this.writeNPY(file.toPath(), ndArray)
72+
73+
public fun <T : Number, D : Dimension> Multik.writeNPY(path: Path, ndArray: NDArray<T, D>): Unit {
74+
when (ndArray.dtype) {
75+
DataType.DoubleDataType -> NpyFile.write(path, ndArray.data.getDoubleArray(), ndArray.shape)
76+
DataType.FloatDataType -> NpyFile.write(path, ndArray.data.getFloatArray(), ndArray.shape)
77+
DataType.IntDataType -> NpyFile.write(path, ndArray.data.getIntArray(), ndArray.shape)
78+
DataType.LongDataType -> NpyFile.write(path, ndArray.data.getLongArray(), ndArray.shape)
79+
DataType.ShortDataType -> NpyFile.write(path, ndArray.data.getShortArray(), ndArray.shape)
80+
DataType.ByteDataType -> NpyFile.write(path, ndArray.data.getByteArray(), ndArray.shape)
81+
else -> TODO()
82+
}
83+
}
84+
85+
public fun Multik.writeNPZ(path: Path, vararg ndArrays: NDArray<out Number, out Dimension>): Unit =
86+
this.writeNPZ(path, ndArrays.asList())
87+
88+
public fun Multik.writeNPZ(path: Path, ndArrays: List<NDArray<out Number, out Dimension>>): Unit {
89+
NpzFile.write(path).use {
90+
ndArrays.forEachIndexed { ind, array ->
91+
when (array.dtype) {
92+
DataType.DoubleDataType -> it.write("arr_$ind", array.data.getDoubleArray(), array.shape)
93+
DataType.FloatDataType -> it.write("arr_$ind", array.data.getFloatArray(), array.shape)
94+
DataType.IntDataType -> it.write("arr_$ind", array.data.getIntArray(), array.shape)
95+
DataType.LongDataType -> it.write("arr_$ind", array.data.getLongArray(), array.shape)
96+
DataType.ShortDataType -> it.write("arr_$ind", array.data.getShortArray(), array.shape)
97+
DataType.ByteDataType -> it.write("arr_$ind", array.data.getByteArray(), array.shape)
98+
else -> TODO()
99+
}
100+
}
101+
}
102+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.jetbrains.kotlinx.multik.io
2+
3+
class UtilsTestsIO
4+
5+
internal fun testResource(resourcePath: String): String =
6+
UtilsTestsIO::class.java.classLoader.getResource(resourcePath)!!.path
7+
8+
internal fun testCsv(csvName: String) = testResource("data/csv/$csvName.csv")
9+
10+
internal fun testNpy(npyName: String) = testResource("data/npy/$npyName.npy")
11+
12+
internal fun testNpz(npzName: String) = testResource("data/npy/$npzName.npz")

0 commit comments

Comments
 (0)