# Multik gives Kotlin a typed N-dimensional array

> Multik is a Kotlin Multiplatform library for N-dimensional arrays with type-safe dimensions, arithmetic, linear algebra and statistics, published in four modules so you can pick a pure Kotlin engine or OpenBLAS acceleration. The trade is that the library is still marked as an alpha, with a JetBrains incubator badge and a 0.3.x version.

**Kotlin/multik** — Multidimensional array library for Kotlin

- Repository: https://github.com/Kotlin/multik
- Website: https://kotlin.github.io/multik/
- Stars: 739 · Forks: 52
- Language: Kotlin
- License: Apache-2.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/kotlin-multik

## Kotlin had no ndarray, and the obvious answer was NumPy

The gap is specific. Kotlin has good collections, but nothing in the standard library models a multidimensional array with a shape, and the existing options each fail in a different direction. A flat List of Lists loses the shape at the type level, so nothing stops you multiplying a 2 by 3 array by a 3 by 2 one and finding out at runtime. Multik fills that gap with N-dimensional arrays with type-safe dimensions, math operations, linear algebra and statistics. The intended user is a Kotlin developer who would otherwise reach for a Java numerical library, and the design goal that shapes everything else is that the same code runs across JVM, JS, WasmJS, iOS and desktop native targets through Kotlin Multiplatform, with optional OpenBLAS acceleration for high performance. The topic tags on the repository say the same thing: kotlin, matrix, multiplatform, ndarray.

## Type-safe dimensions mean the shape is part of the type

The mechanism that distinguishes this from a plain collection is that dimensions are part of the type signature. The README shows an array created with an explicit dimension parameter, mk.ndarray<Float, D2>(setOf(30f, 2f, 13f, 12f), intArrayOf(2, 2)), which creates a two dimensional array from a collection, and the creation functions come in dimension-specific variants such as mk.d2arrayIndices(3, 3) and mk.d3array(2, 2, 3). A separate family of functions builds arrays from primitives and ranges, mk.zeros<Double>(3, 4) for an array of zeros, mk.arange<Long>(10, 25, 5) for elements in the interval with a step, mk.linspace<Double>(0, 2, 9) for evenly spaced elements, mk.identity<Double>(3) for an identity matrix and mk.diagonal for a diagonal array. The shape is then readable back off the instance, with properties for the array dimensions, the size of the array, the Dimension object, the number of array dimensions and the data type of the elements.

## Creation is the most documented part of the API

The README gives more space to array creation than to anything else, and the reason is that this is where the typing decisions become visible. The simplest form wraps a literal list, val a = mk.ndarray(mk[1, 2, 3]), and nesting the bracket operator builds higher dimensions with the shape written out in the source. Then there are the factory functions, and one detail in the docs is worth noticing: the argument order for a shaped primitive array is value first, then dimensions, so mk.ndarray(doubleArrayOf(1.0, 1.3, 3.0, 4.0, 9.5, 5.0), 2, 3) creates an array of shape 2 by 3. The lambda variants take a builder function instead of data, and mk.d3array(2, 2, 3) { it * it } fills a three dimensional array with the square of each index. There is also a lambda variant that receives indices, mk.d2arrayIndices(3, 3) { i, j -> ComplexFloat(i, j) }, which is how you build an array of a non-primitive element type such as a complex number.

## Arithmetic on arrays is elementwise, with broadcasting out of scope

The arithmetic section shows the four basic operations between arrays, and the semantics are plain elementwise arithmetic: subtraction of b and d, addition of d and f, division of b by d and multiplication of f by d, each producing a new array of the same shape. There is no mention of broadcasting rules, matrix multiplication as a distinct operation, or any shape compatibility check beyond what the type system gives you. That is a deliberate narrowing rather than an oversight in the documentation, since the type-safe dimension parameters are what stop a 2 by 3 array from being combined with a 3 by 2 one. The upstream project that inspired the name and the API, NumPy, offers broadcasting and dot products; here the linear algebra API is where that kind of operation belongs, and the README points to the documentation for the mathematics, linear algebra and statistics methods rather than listing them inline.

## Four modules, and the engine is the choice you make

The module structure is the packaging decision that matters, and it is unusually well thought through. multik-core holds the core ndarray types, the mk entry point, and the Math, LinAlg and Statistics API interfaces, and it runs on all platforms. multik-kotlin is the pure Kotlin implementation, working on JVM, JS, WasmJS, iOS and desktop native. multik-openblas is the native implementation backed by OpenBLAS via C++ and JNI, and it covers the JVM and desktop native targets on macOS, Linux and Windows. multik-default combines multik-kotlin and multik-openblas for optimal performance on every platform. In practice you add an engine dependency, one of multik-default, multik-kotlin or multik-openblas, and the engine transitively includes multik-core. The core module on its own gives you the ndarray types, creation functions and basic operations, so a project that only needs array arithmetic does not have to pull in a linear algebra engine.

## The platform table has three blanks and three warnings

The supported platforms table is where the real constraints live, and it has a dash in three cells. multik-openblas is marked as unavailable for JS, WasmJS and the iOS targets, which is expected for a native library reached through JNI, while multik-core, multik-kotlin and multik-default cover all nine listed targets, from the JVM through JS, WasmJS, linuxX64, mingwX64, macosArm64, iosArm64, iosX64 and iosSimulatorArm64. Three warnings follow the table. On Linux distributions with glibc older than 2.31, multik-openblas does not work. The multik-openblas build for desktop native targets is described as experimental and unstable. And the JVM target of multik-openblas for Android supports only arm64-v8a processors. So the acceleration path is available on a modern Linux, on the three desktop natives, and on Android hardware that happens to be arm64, and nowhere else.

## Adding the dependency is three lines of Gradle

Installation is a normal Gradle dependency. The Kotlin DSL form puts the artifact in the dependencies block with the version held in a multikVersion property, and since the engine modules pull in multik-core transitively, that single line is enough:```kotlin
repositories {
    mavenCentral()
}

dependencies {
    implementation("org.jetbrains.kotlinx:multik-default:$multikVersion")
}
```
```There is a Gradle Groovy DSL form as well, with the same coordinates and the same version property, and for a multiplatform project the dependency goes into the commonMain source set instead. The library is also on Maven Central under the org.jetbrains.kotlinx group, and the README shows a Jupyter route for exploring it interactively, using the Kotlin kernel for Jupyter or the Datalore service, and then importing the library in the notebook with a percent use multik directive. The repository itself is a Gradle build with a settings.gradle.kts, a buildSrc directory, a gradle wrapper, and separate module directories for each of the four published modules.

## Alpha status and an incubator badge are the honest headline

Two badges at the top of the README set expectations before anything else. One is the Kotlin Alpha badge, which points at the Kotlin components stability documentation, and the other is the JetBrains incubator project badge. The project also carries a NOTICE file alongside the LICENSE, a CHANGELOG.md, a CONTRIBUTING.md, a CODE_OF_CONDUCT.md and a SECURITY.md at the root, and the licence is the Apache License 2.0. On versioning, the recent tags are 0.3.0 on 2026-03-05, 0.3.1 on 2026-04-22 and v0.2.3 on 2024-02-08, and the default branch is develop rather than main, which is a development branch by convention. The last push to the repository was on 2026-10-13, so work is happening between releases. For a library you would pin and depend on, that combination of an alpha status, an incubator badge and a 0.3.x version is the context to hold.

## Conclusion

Multik suits a Kotlin team that needs an ndarray type and linear algebra in shared common code, and that wants the same source to compile for the JVM, JS, WasmJS, iOS and desktop native targets rather than maintaining a JVM library and a native one. It does not suit a project that needs a stable API today, since the library is marked as a Kotlin Alpha and a JetBrains incubator project, and it does not suit an Android app on an x86 or ARMv7 device expecting OpenBLAS, because the JVM OpenBLAS build supports only arm64-v8a. Before adopting, pick the engine module deliberately, multik-kotlin for portability or multik-openblas for speed, and note that the last push to the repository was on 2026-10-13 while the newest tagged release is 0.3.1 from 2026-04-22.

## FAQ

### How do I add Multik to a Gradle project?

Add the engine dependency in your dependencies block, for example `implementation("org.jetbrains.kotlinx:multik-default:$multikVersion")` in the Kotlin DSL or `implementation "org.jetbrains.kotlinx:multik-default:$multikVersion"` in Groovy. The engine modules include multik-core transitively, so one line is enough.

### What is the difference between the Multik modules?

multik-core holds the ndarray types, the mk entry point and the Math, LinAlg and Statistics interfaces on all platforms. multik-kotlin is the pure Kotlin implementation. multik-openblas is the native implementation backed by OpenBLAS through C++ and JNI, for the JVM and desktop native targets. multik-default combines the Kotlin and OpenBLAS modules.

### Which platforms can run the OpenBLAS accelerated Multik module?

multik-openblas is marked as unavailable for JS, WasmJS and the iOS targets, and the README warns that it does not work on Linux distributions with glibc older than 2.31, that the desktop native build is experimental and unstable, and that the JVM build for Android supports only arm64-v8a processors.

### How do I create a Multik array with a given shape?

The creation functions come in dimension-specific variants, with mk.zeros<Double>(3, 4) making a zero array, mk.d2arrayIndices(3, 3) taking an index lambda, and mk.d3array(2, 2, 3) taking a builder lambda. There are also factories for ranges, mk.arange and mk.linspace, plus mk.identity and mk.diagonal, and the dimension can be stated in the type, as in mk.ndarray<Float, D2>.

### Is Multik stable enough to depend on?

The README carries a Kotlin Alpha badge and a JetBrains incubator project badge, and the newest tagged release is 0.3.1 from 2026-04-22, with the default branch being develop. The last push to the repository was on 2026-10-13, so the code moves between releases.

## Sources

- [Kotlin/multik on GitHub](https://github.com/Kotlin/multik)
- [License: Apache-2.0](https://github.com/Kotlin/multik/blob/develop/LICENSE)
- [Project website](https://kotlin.github.io/multik/)
- [README](https://github.com/Kotlin/multik/blob/develop/README.md)
- [Releases](https://github.com/Kotlin/multik/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/kotlin-multik
