From b442d9d57479a8d0715b2374ed77f80710c81e20 Mon Sep 17 00:00:00 2001 From: Yuriy Davygora Date: Mon, 11 May 2026 22:26:29 +0200 Subject: [PATCH 1/7] Basic Matrix and Matrix Storage implementation --- build.gradle.kts | 2 +- gradle/libs.versions.toml | 2 +- .../duckdns/davygora/matrix/AbstractMatrix.kt | 34 +++++++++++ .../davygora/matrix/AbstractMutableMatrix.kt | 10 ++++ .../org/duckdns/davygora/matrix/Matrix.kt | 11 ++++ .../duckdns/davygora/matrix/MutableMatrix.kt | 9 +++ .../MatrixCoordinateOutOfRangeException.kt | 7 +++ .../matrix/exception/MatrixException.kt | 6 ++ .../exception/MatrixInvalidSizeException.kt | 6 ++ .../exception/MatrixSizeMismatchException.kt | 6 ++ .../davygora/matrix/impl/ArrayMatrix.kt | 57 +++++++++++++++++++ .../davygora/matrix/storage/BooleanStorage.kt | 19 +++++++ .../davygora/matrix/storage/ByteStorage.kt | 19 +++++++ .../davygora/matrix/storage/CharStorage.kt | 19 +++++++ .../davygora/matrix/storage/DoubleStorage.kt | 19 +++++++ .../davygora/matrix/storage/FloatStorage.kt | 19 +++++++ .../davygora/matrix/storage/IntStorage.kt | 19 +++++++ .../davygora/matrix/storage/LongStorage.kt | 19 +++++++ .../davygora/matrix/storage/MatrixStorage.kt | 12 ++++ .../davygora/matrix/storage/ObjectStorage.kt | 19 +++++++ .../davygora/matrix/storage/ShortStorage.kt | 19 +++++++ 21 files changed, 331 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/AbstractMatrix.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/AbstractMutableMatrix.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/Matrix.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/MutableMatrix.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixCoordinateOutOfRangeException.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixException.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixInvalidSizeException.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixSizeMismatchException.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/impl/ArrayMatrix.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/storage/BooleanStorage.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/storage/ByteStorage.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/storage/CharStorage.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/storage/DoubleStorage.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/storage/FloatStorage.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/storage/IntStorage.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/storage/LongStorage.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorage.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/storage/ObjectStorage.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/storage/ShortStorage.kt diff --git a/build.gradle.kts b/build.gradle.kts index 26cc008..af0a95e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -35,7 +35,7 @@ kotlin { kotlin { jvmToolchain { - languageVersion = JavaLanguageVersion.of(25) + languageVersion = JavaLanguageVersion.of(21) vendor = JvmVendorSpec.ADOPTIUM } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8c2419b..0aa6002 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ mockk = "1.14.9" # https://mvnrepository.com/artifact/io.mockk/mockk kotlin-reflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlin" } -memoize = {group = "org.duckdns.davygora", name = "memoize", version.ref="memoize"} +memoize = { group = "org.duckdns.davygora", name = "memoize", version.ref = "memoize" } # Test diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/AbstractMatrix.kt b/src/main/kotlin/org/duckdns/davygora/matrix/AbstractMatrix.kt new file mode 100644 index 0000000..85d7b88 --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/AbstractMatrix.kt @@ -0,0 +1,34 @@ +package org.duckdns.davygora.matrix + +import org.duckdns.davygora.matrix.storage.MatrixStorage + +abstract class AbstractMatrix( + override val xSize: Int, + override val ySize: Int, + protected val matrix: MatrixStorage, +) : Matrix { + override fun toString(): String = + (0.. + "[\t${(0.. this[x, y].toString() }}\t]" + }.joinToString { "\n" } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as AbstractMatrix + + if (xSize != other.xSize) return false + if (ySize != other.ySize) return false + if (matrix != other.matrix) return false + return true + } + + override fun hashCode(): Int { + var result = xSize + result = 31 * result + ySize + result = 31 * result + matrix.hashCode() + return result + } +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/AbstractMutableMatrix.kt b/src/main/kotlin/org/duckdns/davygora/matrix/AbstractMutableMatrix.kt new file mode 100644 index 0000000..8ddea6e --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/AbstractMutableMatrix.kt @@ -0,0 +1,10 @@ +package org.duckdns.davygora.matrix + +import org.duckdns.davygora.matrix.storage.MatrixStorage + +abstract class AbstractMutableMatrix( + xSize: Int, + ySize: Int, + matrix: MatrixStorage, +) : AbstractMatrix(xSize, ySize, matrix), + MutableMatrix diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/Matrix.kt b/src/main/kotlin/org/duckdns/davygora/matrix/Matrix.kt new file mode 100644 index 0000000..4d3fcb9 --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/Matrix.kt @@ -0,0 +1,11 @@ +package org.duckdns.davygora.matrix + +interface Matrix { + val xSize: Int + val ySize: Int + + operator fun get( + x: Int, + y: Int, + ): T +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/MutableMatrix.kt b/src/main/kotlin/org/duckdns/davygora/matrix/MutableMatrix.kt new file mode 100644 index 0000000..7261763 --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/MutableMatrix.kt @@ -0,0 +1,9 @@ +package org.duckdns.davygora.matrix + +interface MutableMatrix : Matrix { + operator fun set( + x: Int, + y: Int, + value: T, + ) +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixCoordinateOutOfRangeException.kt b/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixCoordinateOutOfRangeException.kt new file mode 100644 index 0000000..8b5d0d5 --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixCoordinateOutOfRangeException.kt @@ -0,0 +1,7 @@ +package org.duckdns.davygora.matrix.exception + +class MatrixCoordinateOutOfRangeException( + coordName: Char, + coord: Int, + maxCoord: Int, +) : MatrixException("${coordName.uppercaseChar()} coordinate $coord is out of range, allowed is 0..$maxCoord") diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixException.kt b/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixException.kt new file mode 100644 index 0000000..8ffddd3 --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixException.kt @@ -0,0 +1,6 @@ +package org.duckdns.davygora.matrix.exception + +sealed class MatrixException( + message: String, + cause: Throwable? = null, +) : RuntimeException(message, cause) diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixInvalidSizeException.kt b/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixInvalidSizeException.kt new file mode 100644 index 0000000..d8deb5d --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixInvalidSizeException.kt @@ -0,0 +1,6 @@ +package org.duckdns.davygora.matrix.exception + +class MatrixInvalidSizeException( + coordinate: Char, + size: Int, +) : MatrixException("${coordinate.uppercaseChar()} size is invalid: $size (should be > 0)") diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixSizeMismatchException.kt b/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixSizeMismatchException.kt new file mode 100644 index 0000000..9847ed1 --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixSizeMismatchException.kt @@ -0,0 +1,6 @@ +package org.duckdns.davygora.matrix.exception + +class MatrixSizeMismatchException( + expectedSize: Int, + actualSize: Int, +) : MatrixException("Matrix size mismatch: expected $expectedSize, actual $actualSize") diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/impl/ArrayMatrix.kt b/src/main/kotlin/org/duckdns/davygora/matrix/impl/ArrayMatrix.kt new file mode 100644 index 0000000..5dc8fe2 --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/impl/ArrayMatrix.kt @@ -0,0 +1,57 @@ +package org.duckdns.davygora.matrix.impl + +import org.duckdns.davygora.matrix.AbstractMutableMatrix +import org.duckdns.davygora.matrix.Matrix +import org.duckdns.davygora.matrix.exception.MatrixCoordinateOutOfRangeException +import org.duckdns.davygora.matrix.exception.MatrixInvalidSizeException +import org.duckdns.davygora.matrix.exception.MatrixNotRectangularException +import org.duckdns.davygora.matrix.exception.MatrixSizeMismatchException +import org.duckdns.davygora.matrix.storage.MatrixStorage +import org.duckdns.davygora.memoize.memoize + +class ArrayMatrix( + xSize: Int, + ySize: Int, + matrix: MatrixStorage, +) : AbstractMutableMatrix(xSize, ySize, matrix) { + private val size = xSize * ySize + + private val maxX = xSize - 1 + private val maxY = ySize - 1 + + init { + if (ySize < 1) throw MatrixInvalidSizeException('y', ySize) + if (xSize < 1) throw MatrixInvalidSizeException('x', xSize) + if (size != matrix.size) throw MatrixSizeMismatchException(size, matrix.size) + } + + override operator fun get( + x: Int, + y: Int, + ): T = matrix[index(x, y)] + + override operator fun set( + x: Int, + y: Int, + value: T, + ) { + matrix[index(x, y)] = value + } + + private val index = { x: Int, y: Int -> validateY(y) * xSize + validateX(x) }.memoize() + + private val validateX = { x: Int -> validateCoord('x', x, maxX) }.memoize() + private val validateY = { y: Int -> validateCoord('y', y, maxY) }.memoize() + + private fun validateCoord( + coordName: Char, + coord: Int, + maxCoord: Int, + ) = if (coord in + 0..maxCoord + ) { + coord + } else { + throw MatrixCoordinateOutOfRangeException(coordName, coord, maxCoord) + } +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/BooleanStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/BooleanStorage.kt new file mode 100644 index 0000000..6243d0b --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/BooleanStorage.kt @@ -0,0 +1,19 @@ +package org.duckdns.davygora.matrix.storage + +@JvmInline +value class BooleanStorage( + val data: BooleanArray, +) : MatrixStorage { + override val size get() = data.size + + override operator fun get(index: Int) = data[index] + + override fun set( + index: Int, + value: Boolean, + ) { + data[index] = value + } + + override fun toString(): String = data.contentToString() +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ByteStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ByteStorage.kt new file mode 100644 index 0000000..21dd502 --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ByteStorage.kt @@ -0,0 +1,19 @@ +package org.duckdns.davygora.matrix.storage + +@JvmInline +value class ByteStorage( + val data: ByteArray, +) : MatrixStorage { + override val size get() = data.size + + override operator fun get(index: Int) = data[index] + + override fun set( + index: Int, + value: Byte, + ) { + data[index] = value + } + + override fun toString(): String = data.contentToString() +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/CharStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/CharStorage.kt new file mode 100644 index 0000000..52dd8ed --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/CharStorage.kt @@ -0,0 +1,19 @@ +package org.duckdns.davygora.matrix.storage + +@JvmInline +value class CharStorage( + val data: CharArray, +) : MatrixStorage { + override val size get() = data.size + + override operator fun get(index: Int) = data[index] + + override fun set( + index: Int, + value: Char, + ) { + data[index] = value + } + + override fun toString(): String = data.contentToString() +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/DoubleStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/DoubleStorage.kt new file mode 100644 index 0000000..7ed8d3f --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/DoubleStorage.kt @@ -0,0 +1,19 @@ +package org.duckdns.davygora.matrix.storage + +@JvmInline +value class DoubleStorage( + val data: DoubleArray, +) : MatrixStorage { + override val size get() = data.size + + override operator fun get(index: Int) = data[index] + + override fun set( + index: Int, + value: Double, + ) { + data[index] = value + } + + override fun toString(): String = data.contentToString() +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/FloatStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/FloatStorage.kt new file mode 100644 index 0000000..bde36c9 --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/FloatStorage.kt @@ -0,0 +1,19 @@ +package org.duckdns.davygora.matrix.storage + +@JvmInline +value class FloatStorage( + val data: FloatArray, +) : MatrixStorage { + override val size get() = data.size + + override operator fun get(index: Int) = data[index] + + override fun set( + index: Int, + value: Float, + ) { + data[index] = value + } + + override fun toString(): String = data.contentToString() +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/IntStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/IntStorage.kt new file mode 100644 index 0000000..ca3cd7b --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/IntStorage.kt @@ -0,0 +1,19 @@ +package org.duckdns.davygora.matrix.storage + +@JvmInline +value class IntStorage( + val data: IntArray, +) : MatrixStorage { + override val size get() = data.size + + override operator fun get(index: Int) = data[index] + + override fun set( + index: Int, + value: Int, + ) { + data[index] = value + } + + override fun toString(): String = data.contentToString() +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/LongStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/LongStorage.kt new file mode 100644 index 0000000..e1fe2ce --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/LongStorage.kt @@ -0,0 +1,19 @@ +package org.duckdns.davygora.matrix.storage + +@JvmInline +value class LongStorage( + val data: LongArray, +) : MatrixStorage { + override val size get() = data.size + + override operator fun get(index: Int) = data[index] + + override fun set( + index: Int, + value: Long, + ) { + data[index] = value + } + + override fun toString(): String = data.contentToString() +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorage.kt new file mode 100644 index 0000000..db672aa --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorage.kt @@ -0,0 +1,12 @@ +package org.duckdns.davygora.matrix.storage + +sealed interface MatrixStorage { + val size: Int + + operator fun get(index: Int): T + + operator fun set( + index: Int, + value: T, + ) +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ObjectStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ObjectStorage.kt new file mode 100644 index 0000000..964af74 --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ObjectStorage.kt @@ -0,0 +1,19 @@ +package org.duckdns.davygora.matrix.storage + +@JvmInline +value class ObjectStorage( + val data: Array, +) : MatrixStorage { + override val size get() = data.size + + override operator fun get(index: Int) = data[index] + + override fun set( + index: Int, + value: T, + ) { + data[index] = value + } + + override fun toString(): String = data.contentToString() +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ShortStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ShortStorage.kt new file mode 100644 index 0000000..9cbf877 --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ShortStorage.kt @@ -0,0 +1,19 @@ +package org.duckdns.davygora.matrix.storage + +@JvmInline +value class ShortStorage( + val data: ShortArray, +) : MatrixStorage { + override val size get() = data.size + + override operator fun get(index: Int) = data[index] + + override fun set( + index: Int, + value: Short, + ) { + data[index] = value + } + + override fun toString(): String = data.contentToString() +} -- 2.54.0 From db51aecca1286c9159493cfd548e54aa33c0ea21 Mon Sep 17 00:00:00 2001 From: Yuriy Davygora Date: Tue, 12 May 2026 08:44:07 +0200 Subject: [PATCH 2/7] Adding companion create method --- .../MatrixNotRectangularException.kt | 5 +++++ .../davygora/matrix/impl/ArrayMatrix.kt | 22 ++++++++++++++++++- .../davygora/matrix/storage/BooleanStorage.kt | 2 ++ .../davygora/matrix/storage/ByteStorage.kt | 2 ++ .../davygora/matrix/storage/CharStorage.kt | 2 ++ .../davygora/matrix/storage/DoubleStorage.kt | 2 ++ .../davygora/matrix/storage/FloatStorage.kt | 2 ++ .../davygora/matrix/storage/IntStorage.kt | 2 ++ .../davygora/matrix/storage/LongStorage.kt | 2 ++ .../davygora/matrix/storage/MatrixStorage.kt | 14 ++++++++++++ .../davygora/matrix/storage/ObjectStorage.kt | 2 ++ .../davygora/matrix/storage/ShortStorage.kt | 2 ++ 12 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixNotRectangularException.kt diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixNotRectangularException.kt b/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixNotRectangularException.kt new file mode 100644 index 0000000..6f44506 --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/exception/MatrixNotRectangularException.kt @@ -0,0 +1,5 @@ +package org.duckdns.davygora.matrix.exception + +class MatrixNotRectangularException( + xSizes: Collection, +) : MatrixException("Submitted matrix is not rectangular, different row sizes are $xSizes") diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/impl/ArrayMatrix.kt b/src/main/kotlin/org/duckdns/davygora/matrix/impl/ArrayMatrix.kt index 5dc8fe2..87f3b8d 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/impl/ArrayMatrix.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/impl/ArrayMatrix.kt @@ -1,12 +1,12 @@ package org.duckdns.davygora.matrix.impl import org.duckdns.davygora.matrix.AbstractMutableMatrix -import org.duckdns.davygora.matrix.Matrix import org.duckdns.davygora.matrix.exception.MatrixCoordinateOutOfRangeException import org.duckdns.davygora.matrix.exception.MatrixInvalidSizeException import org.duckdns.davygora.matrix.exception.MatrixNotRectangularException import org.duckdns.davygora.matrix.exception.MatrixSizeMismatchException import org.duckdns.davygora.matrix.storage.MatrixStorage +import org.duckdns.davygora.matrix.storage.toMatrixStorage import org.duckdns.davygora.memoize.memoize class ArrayMatrix( @@ -54,4 +54,24 @@ class ArrayMatrix( } else { throw MatrixCoordinateOutOfRangeException(coordName, coord, maxCoord) } + + companion object { + inline fun create(values: List>): ArrayMatrix { + val ySize = values.size + val xSize = + when { + ySize > 0 -> { + values.map { row -> row.size }.toSet().let { xSizes -> + if (xSizes.size == 1) xSizes.first() else throw MatrixNotRectangularException(xSizes) + } + } + + else -> { + 0 + } + } + + return ArrayMatrix(xSize, ySize, values.flatten().toMatrixStorage()) + } + } } diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/BooleanStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/BooleanStorage.kt index 6243d0b..2fcd4e9 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/BooleanStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/BooleanStorage.kt @@ -17,3 +17,5 @@ value class BooleanStorage( override fun toString(): String = data.contentToString() } + +fun BooleanArray.toMatrixStorage() = BooleanStorage(this) diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ByteStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ByteStorage.kt index 21dd502..45488b4 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ByteStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ByteStorage.kt @@ -17,3 +17,5 @@ value class ByteStorage( override fun toString(): String = data.contentToString() } + +fun ByteArray.toMatrixStorage() = ByteStorage(this) diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/CharStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/CharStorage.kt index 52dd8ed..2390306 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/CharStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/CharStorage.kt @@ -17,3 +17,5 @@ value class CharStorage( override fun toString(): String = data.contentToString() } + +fun CharArray.toMatrixStorage() = CharStorage(this) diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/DoubleStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/DoubleStorage.kt index 7ed8d3f..613c044 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/DoubleStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/DoubleStorage.kt @@ -17,3 +17,5 @@ value class DoubleStorage( override fun toString(): String = data.contentToString() } + +fun DoubleArray.toMatrixStorage() = DoubleStorage(this) diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/FloatStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/FloatStorage.kt index bde36c9..6cd73e2 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/FloatStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/FloatStorage.kt @@ -17,3 +17,5 @@ value class FloatStorage( override fun toString(): String = data.contentToString() } + +fun FloatArray.toMatrixStorage() = FloatStorage(this) diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/IntStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/IntStorage.kt index ca3cd7b..1f3c81b 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/IntStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/IntStorage.kt @@ -17,3 +17,5 @@ value class IntStorage( override fun toString(): String = data.contentToString() } + +fun IntArray.toMatrixStorage() = IntStorage(this) diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/LongStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/LongStorage.kt index e1fe2ce..10fee68 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/LongStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/LongStorage.kt @@ -17,3 +17,5 @@ value class LongStorage( override fun toString(): String = data.contentToString() } + +fun LongArray.toMatrixStorage() = LongStorage(this) diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorage.kt index db672aa..2f1fd45 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorage.kt @@ -10,3 +10,17 @@ sealed interface MatrixStorage { value: T, ) } + +@Suppress("UNCHECKED_CAST") +inline fun List.toMatrixStorage() = + when (T::class) { + Boolean::class -> (this as List).toBooleanArray().toMatrixStorage() + Byte::class -> (this as List).toByteArray().toMatrixStorage() + Char::class -> (this as List).toCharArray().toMatrixStorage() + Double::class -> (this as List).toDoubleArray().toMatrixStorage() + Float::class -> (this as List).toFloatArray().toMatrixStorage() + Int::class -> (this as List).toIntArray().toMatrixStorage() + Long::class -> (this as List).toLongArray().toMatrixStorage() + Short::class -> (this as List).toShortArray().toMatrixStorage() + else -> this.toTypedArray().toMatrixStorage() + } as MatrixStorage diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ObjectStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ObjectStorage.kt index 964af74..3b7b66b 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ObjectStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ObjectStorage.kt @@ -17,3 +17,5 @@ value class ObjectStorage( override fun toString(): String = data.contentToString() } + +fun Array.toMatrixStorage() = ObjectStorage(this) diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ShortStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ShortStorage.kt index 9cbf877..a3b0b1b 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ShortStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ShortStorage.kt @@ -17,3 +17,5 @@ value class ShortStorage( override fun toString(): String = data.contentToString() } + +fun ShortArray.toMatrixStorage() = ShortStorage(this) -- 2.54.0 From 5c42826e6602c2606c26840a7a0bf7f9ce21be2a Mon Sep 17 00:00:00 2001 From: Yuriy Davygora Date: Tue, 12 May 2026 12:37:53 +0200 Subject: [PATCH 3/7] Adding some extensions --- .../davygora/matrix/impl/MatrixExtentions.kt | 24 +++++++++++++++++++ .../davygora/matrix/util/IterableUtils.kt | 22 +++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/impl/MatrixExtentions.kt create mode 100644 src/main/kotlin/org/duckdns/davygora/matrix/util/IterableUtils.kt diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/impl/MatrixExtentions.kt b/src/main/kotlin/org/duckdns/davygora/matrix/impl/MatrixExtentions.kt new file mode 100644 index 0000000..b36b416 --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/impl/MatrixExtentions.kt @@ -0,0 +1,24 @@ +package org.duckdns.davygora.matrix.impl + +import org.duckdns.davygora.matrix.Matrix +import org.duckdns.davygora.matrix.MutableMatrix +import org.duckdns.davygora.matrix.storage.toMatrixStorage +import org.duckdns.davygora.matrix.util.toListChecked + +inline fun mutableMatrixOf( + xSize: Int, + ySize: Int, + vararg matrix: T, +) = ArrayMatrix(xSize, ySize, matrix.asList().toMatrixStorage()) as MutableMatrix + +inline fun matrixOf( + xSize: Int, + ySize: Int, + vararg matrix: T, +) = mutableMatrixOf(xSize, ySize, *matrix) as Matrix + +inline fun Iterable.toMatrix() = ArrayMatrix.create(this.map { it.toListChecked() }) + +inline fun Array.toMatrix() = this.asList().toMatrix() + +inline fun Sequence.toMatrix() = this.toList().toMatrix() diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/util/IterableUtils.kt b/src/main/kotlin/org/duckdns/davygora/matrix/util/IterableUtils.kt new file mode 100644 index 0000000..835c26d --- /dev/null +++ b/src/main/kotlin/org/duckdns/davygora/matrix/util/IterableUtils.kt @@ -0,0 +1,22 @@ +package org.duckdns.davygora.matrix.util + +@Suppress("UNCHECKED_CAST") +inline fun Any.toListChecked(): List = + when (this) { + is List<*> -> this + is Collection<*> -> this.toList() + is Iterable<*> -> this.toList() + is Sequence<*> -> this.toList() + is Array<*> -> this.asList() + is BooleanArray -> this.asList() + is ByteArray -> this.asList() + is CharArray -> this.asList() + is DoubleArray -> this.asList() + is FloatArray -> this.asList() + is IntArray -> this.asList() + is LongArray -> this.asList() + is ShortArray -> this.asList() + else -> error("Unsupported type: ${this::class}") + }.also { list -> + require(list.all { it is T }) + } as List -- 2.54.0 From 5cbf9f4a14bc18292cc2ca38e4e7f3090e90c8c7 Mon Sep 17 00:00:00 2001 From: Yuriy Davygora Date: Wed, 13 May 2026 09:38:06 +0200 Subject: [PATCH 4/7] Adding MatrixStorageTest --- .../davygora/matrix/storage/BooleanStorage.kt | 2 +- .../davygora/matrix/storage/ByteStorage.kt | 2 +- .../davygora/matrix/storage/CharStorage.kt | 2 +- .../davygora/matrix/storage/DoubleStorage.kt | 2 +- .../davygora/matrix/storage/FloatStorage.kt | 2 +- .../davygora/matrix/storage/IntStorage.kt | 2 +- .../davygora/matrix/storage/LongStorage.kt | 2 +- .../davygora/matrix/storage/MatrixStorage.kt | 17 ++++++- .../davygora/matrix/storage/ObjectStorage.kt | 2 +- .../davygora/matrix/storage/ShortStorage.kt | 2 +- .../matrix/storage/MatrixStorageTest.kt | 50 +++++++++++++++++++ 11 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 src/test/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorageTest.kt diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/BooleanStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/BooleanStorage.kt index 2fcd4e9..24d9779 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/BooleanStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/BooleanStorage.kt @@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage @JvmInline value class BooleanStorage( - val data: BooleanArray, + override val data: BooleanArray, ) : MatrixStorage { override val size get() = data.size diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ByteStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ByteStorage.kt index 45488b4..d9734f6 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ByteStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ByteStorage.kt @@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage @JvmInline value class ByteStorage( - val data: ByteArray, + override val data: ByteArray, ) : MatrixStorage { override val size get() = data.size diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/CharStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/CharStorage.kt index 2390306..ce75597 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/CharStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/CharStorage.kt @@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage @JvmInline value class CharStorage( - val data: CharArray, + override val data: CharArray, ) : MatrixStorage { override val size get() = data.size diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/DoubleStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/DoubleStorage.kt index 613c044..f4e1d72 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/DoubleStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/DoubleStorage.kt @@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage @JvmInline value class DoubleStorage( - val data: DoubleArray, + override val data: DoubleArray, ) : MatrixStorage { override val size get() = data.size diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/FloatStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/FloatStorage.kt index 6cd73e2..c886995 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/FloatStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/FloatStorage.kt @@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage @JvmInline value class FloatStorage( - val data: FloatArray, + override val data: FloatArray, ) : MatrixStorage { override val size get() = data.size diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/IntStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/IntStorage.kt index 1f3c81b..60fcb56 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/IntStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/IntStorage.kt @@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage @JvmInline value class IntStorage( - val data: IntArray, + override val data: IntArray, ) : MatrixStorage { override val size get() = data.size diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/LongStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/LongStorage.kt index 10fee68..033645b 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/LongStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/LongStorage.kt @@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage @JvmInline value class LongStorage( - val data: LongArray, + override val data: LongArray, ) : MatrixStorage { override val size get() = data.size diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorage.kt index 2f1fd45..207b2e0 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorage.kt @@ -1,6 +1,8 @@ package org.duckdns.davygora.matrix.storage sealed interface MatrixStorage { + val data: Any + val size: Int operator fun get(index: Int): T @@ -12,8 +14,18 @@ sealed interface MatrixStorage { } @Suppress("UNCHECKED_CAST") -inline fun List.toMatrixStorage() = - when (T::class) { +inline fun List.toMatrixStorage(): MatrixStorage { + firstNotNullOfOrNull { it } + + val elementClass = + firstOrNull() + ?.let { first -> first::class } + ?.takeIf { clazz -> + all { it == null || it::class == clazz } + } + ?: T::class + + return when (elementClass) { Boolean::class -> (this as List).toBooleanArray().toMatrixStorage() Byte::class -> (this as List).toByteArray().toMatrixStorage() Char::class -> (this as List).toCharArray().toMatrixStorage() @@ -24,3 +36,4 @@ inline fun List.toMatrixStorage() = Short::class -> (this as List).toShortArray().toMatrixStorage() else -> this.toTypedArray().toMatrixStorage() } as MatrixStorage +} diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ObjectStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ObjectStorage.kt index 3b7b66b..80066e3 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ObjectStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ObjectStorage.kt @@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage @JvmInline value class ObjectStorage( - val data: Array, + override val data: Array, ) : MatrixStorage { override val size get() = data.size diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ShortStorage.kt b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ShortStorage.kt index a3b0b1b..c9deb80 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/storage/ShortStorage.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/storage/ShortStorage.kt @@ -2,7 +2,7 @@ package org.duckdns.davygora.matrix.storage @JvmInline value class ShortStorage( - val data: ShortArray, + override val data: ShortArray, ) : MatrixStorage { override val size get() = data.size diff --git a/src/test/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorageTest.kt b/src/test/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorageTest.kt new file mode 100644 index 0000000..f1e9add --- /dev/null +++ b/src/test/kotlin/org/duckdns/davygora/matrix/storage/MatrixStorageTest.kt @@ -0,0 +1,50 @@ +package org.duckdns.davygora.matrix.storage + +import io.kotest.core.spec.style.FunSpec +import io.kotest.datatest.withData +import io.kotest.matchers.shouldBe +import kotlin.reflect.KClass + +class MatrixStorageTest : + FunSpec({ + val testCases: Map, KClass<*>, KClass<*>>> = + mapOf( + "boolean" to Triple(listOf(true, false), BooleanStorage::class, BooleanArray::class), + "byte" to Triple((0..100).map { it.toByte() }, ByteStorage::class, ByteArray::class), + "char" to Triple(('a'..'z') + ('A'..'Z') + ('0'..'9'), CharStorage::class, CharArray::class), + "double" to Triple((0..100).map { it.toDouble() }, DoubleStorage::class, DoubleArray::class), + "float" to Triple((0..100).map { it.toFloat() }, FloatStorage::class, FloatArray::class), + "int" to Triple((0..100).map { it }, IntStorage::class, IntArray::class), + "long" to Triple((0..100).map { it.toLong() }, LongStorage::class, LongArray::class), + "short" to Triple((0..100).map { it.toShort() }, ShortStorage::class, ShortArray::class), + "object" to Triple((0..100).map { first -> Pair(first, (0..100).random()) }, ObjectStorage::class, Array::class), + ) + + context("list of elements of a given type should produce corresponding storage, size, get and set should work") { + withData( + testCases, + ) { (allowedValues, storageClass, dataClass) -> + + // Arrange + + val size = (10..1000).random() + val list = List(size) { allowedValues.random() } + val newList = List(size) { allowedValues.random() } + + // Act + + val storage = list.toMatrixStorage() + + // Assert + + storage::class shouldBe storageClass + storage.data::class shouldBe dataClass + + storage.size shouldBe size + list.forEachIndexed { index, value -> storage[index] shouldBe value } + + newList.forEachIndexed { index, value -> storage[index] = value } + newList.forEachIndexed { index, value -> storage[index] shouldBe value } + } + } + }) -- 2.54.0 From 84e7b25468fde5a1424ac2d4c8522b084c40b8da Mon Sep 17 00:00:00 2001 From: Yuriy Davygora Date: Wed, 13 May 2026 09:42:42 +0200 Subject: [PATCH 5/7] Just a little improvement, no code change --- .../davygora/matrix/util/IterableUtils.kt | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/org/duckdns/davygora/matrix/util/IterableUtils.kt b/src/main/kotlin/org/duckdns/davygora/matrix/util/IterableUtils.kt index 835c26d..32ca064 100644 --- a/src/main/kotlin/org/duckdns/davygora/matrix/util/IterableUtils.kt +++ b/src/main/kotlin/org/duckdns/davygora/matrix/util/IterableUtils.kt @@ -4,18 +4,18 @@ package org.duckdns.davygora.matrix.util inline fun Any.toListChecked(): List = when (this) { is List<*> -> this - is Collection<*> -> this.toList() - is Iterable<*> -> this.toList() - is Sequence<*> -> this.toList() - is Array<*> -> this.asList() - is BooleanArray -> this.asList() - is ByteArray -> this.asList() - is CharArray -> this.asList() - is DoubleArray -> this.asList() - is FloatArray -> this.asList() - is IntArray -> this.asList() - is LongArray -> this.asList() - is ShortArray -> this.asList() + is Collection<*> -> toList() + is Iterable<*> -> toList() + is Sequence<*> -> toList() + is Array<*> -> asList() + is BooleanArray -> asList() + is ByteArray -> asList() + is CharArray -> asList() + is DoubleArray -> asList() + is FloatArray -> asList() + is IntArray -> asList() + is LongArray -> asList() + is ShortArray -> asList() else -> error("Unsupported type: ${this::class}") }.also { list -> require(list.all { it is T }) -- 2.54.0 From f85ac3f76e61713bfb49d98f89dd5ea177ec3dc9 Mon Sep 17 00:00:00 2001 From: Yuriy Davygora Date: Wed, 13 May 2026 13:55:16 +0200 Subject: [PATCH 6/7] Bumping gradle version --- gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0aa6002..52db737 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ # Main -gradle = "9.5.0" # https://gradle.org/releases/ +gradle = "9.5.1" # https://gradle.org/releases/ kotlin = "2.3.21" # https://kotlinlang.org/docs/releases.html#release-details diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b52fb7e..df6a6ad 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/gradlew b/gradlew index f640dbc..b9bb139 100755 --- a/gradlew +++ b/gradlew @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob//platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. -- 2.54.0 From 2124b8b22922fee53ea963d4f5672793b94ccc99 Mon Sep 17 00:00:00 2001 From: Yuriy Davygora Date: Wed, 13 May 2026 14:05:30 +0200 Subject: [PATCH 7/7] Adding LICENSE and a dummy README --- LICENSE | 0 README.md | 3 +++ 2 files changed, 3 insertions(+) create mode 100644 LICENSE create mode 100644 README.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md new file mode 100644 index 0000000..bb12c88 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Matrix + +TODO -- 2.54.0